Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

ClinicalTrials.Gov Server — OncoHub

БесплатноНе проверен

A production-quality MCP server that wraps the ClinicalTrials.gov v2 API, providing structured, TTL-cached access to trial data worldwide and Turkey via 4 MCP t

GitHubEmbed

Описание

A production-quality MCP server that wraps the ClinicalTrials.gov v2 API, providing structured, TTL-cached access to trial data worldwide and Turkey via 4 MCP tools.

README

A production-quality MCP (Model Context Protocol) server that wraps the ClinicalTrials.gov v2 API. Designed for the OncoHub Tumor Council as the data source for clinical_trial_matching_module v2 / A2.3.

What this server does: structured, TTL-cached access to CT.gov trial data (worldwide + Turkey) via 4 MCP tools. What it does not do: clinical eligibility assessment, scoring, or any form of clinical judgment — that is the consuming system's responsibility.


Why Python + FastMCP?

  • CT.gov v2 is a plain JSON REST API — no special SDK needed
  • FastMCP's HTTP transport satisfies claude.ai's remote connector requirement (STDIO won't work there)
  • httpx + asyncio give clean async retry/backoff
  • SQLite cache requires zero infrastructure beyond the process itself

Project Structure

CT-MSP/
├── server.py          # FastMCP server + 4 MCP tools (entry point)
├── ctgov_client.py    # Async httpx client, rate limiting, retry
├── normalize.py       # Raw CT.gov JSON → flat OncoHub schema
├── cache.py           # SQLite TTL cache (no external deps)
├── models.py          # Pydantic models (schema documentation)
├── tests/
│   ├── conftest.py    # Shared fixtures + sample API responses
│   ├── test_normalize.py
│   ├── test_client.py
│   ├── test_cache.py
│   ├── test_tools.py  # MCP tool integration tests (mocked)
│   └── test_smoke.py  # Live API smoke tests (opt-in)
├── Dockerfile
├── render.yaml        # One-click Render deployment
├── pyproject.toml
└── .env.example

Local Setup

Requirements: Python 3.11+, pip

# 1. Clone / navigate to project directory
cd CT-MSP

# 2. Create virtual environment
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate

# 3. Install dependencies
pip install -e ".[dev]"

# 4. Configure environment
cp .env.example .env
# Edit .env if needed (defaults work for local development)

# 5. Run the server
python server.py
# Server starts on http://localhost:8000
# MCP endpoint: http://localhost:8000/mcp

Test with MCP Inspector

npx @modelcontextprotocol/inspector http://localhost:8000/mcp

This opens a browser UI where you can call tools interactively.

Run tests

pytest                         # all unit tests (no network)
pytest -m smoke                # live CT.gov smoke tests (requires internet)
pytest tests/test_normalize.py # specific module

Public Deployment

Required for claude.ai connector — claude.ai only connects to public HTTPS endpoints.

Option A: Render (recommended — free tier, auto-HTTPS)

  1. Push this repo to GitHub.
  2. Go to render.comNewWeb Service → connect your repo.
  3. Render auto-detects render.yaml — click Apply.
  4. Wait ~3 min for the first build.
  5. Your URL: https://ctgov-mcp-oncohub.onrender.com (or your custom name).
  6. Free tier caveat: the service sleeps after 15 min of inactivity (first request takes ~30s to wake). The SQLite cache resets on restart since /tmp is ephemeral. Upgrade to Starter ($7/mo) for a persistent disk (/data).

Persistent disk (Starter plan): uncomment the disk: section in render.yaml and set CACHE_PATH=/data/ctgov.db.

Option B: Railway

# Install Railway CLI
npm i -g @railway/cli
railway login
railway init
railway up

Set environment variables via railway variables set STATUS_TTL_DAYS=7 ...

Option C: Fly.io

fly launch       # detects Dockerfile automatically
fly deploy
fly secrets set STATUS_TTL_DAYS=7 META_TTL_DAYS=30

Add a volume for persistent cache:

fly volumes create ctgov_cache --size 1

Then set CACHE_PATH=/data/ctgov.db in fly.toml.

Option D: Any Docker host

docker build -t ctgov-mcp .
docker run -p 8000:8000 \
  -e STATUS_TTL_DAYS=7 \
  -v ctgov_cache:/data \
  -e CACHE_PATH=/data/ctgov.db \
  ctgov-mcp

Adding to claude.ai as a Custom Connector

Prerequisites:

  • Server running at a public HTTPS URL (e.g. https://ctgov-mcp-oncohub.onrender.com)
  • claude.ai Pro, Team, or Enterprise plan
  • OncoHub Project must be private

Steps (Individual / Pro)

  1. Go to claude.ai → [Your name] → Settings → Connectors.
  2. Click "+""Add custom connector".
  3. Name: ClinicalTrials.gov (OncoHub)
  4. URL: https://<your-host>/mcp
  5. Auth: leave OAuth fields blank (this server has no auth).
  6. Click Add.

Steps (Team / Enterprise)

  1. An Owner goes to Organization Settings → Connectors → Add connector (same fields as above).
  2. Members connect it via [+] → Connectors in any conversation.

Activating in the Tumor Council Project

  1. Open the OncoHub project.
  2. In a conversation, click "+" (bottom-left) → Connectors.
  3. Toggle ClinicalTrials.gov (OncoHub) ON.
  4. The system prompt should reference tool names (e.g. dual_source_search) for the module to call them automatically during report generation.

Note: claude_desktop_config.json (STDIO transport) does NOT work with claude.ai Projects — only remote HTTP/SSE connectors work there.


MCP Tools Reference

dual_source_search ← Primary council entry point

Searches worldwide AND Turkey in two sequential calls, merges by NCT ID, marks has_turkey_site.

Parameter Type Default Description
condition str required Disease/condition (maps from A1 tumor field)
term str? null Biomarker / keyword (maps from A1 biomarker field)
intervention str? null Drug or target (maps from A1 treatment field)
statuses list[str]? RECRUITING, NOT_YET_RECRUITING Overall status filter
phases list[str]? null Phase filter (maps from A1 treatment line)
page_size int 20 Results per sub-query (max 50)
force_refresh bool false Skip cache

Returns: {studies: [...], total_count, turkey_count, next_page_token, note}


search_trials

Parameterized worldwide search.

Parameter Type Default Description
condition str required Disease/condition
term str? null Free-text biomarker or keyword
intervention str? null Drug or target
statuses list[str]? RECRUITING, NOT_YET_RECRUITING See valid values below
phases list[str]? null See valid values below
country str? null Country name for location filter
page_size int 20 Max 50 recommended
page_token str? null Pagination cursor
force_refresh bool false Skip cache

Valid statuses: RECRUITING, NOT_YET_RECRUITING, ACTIVE_NOT_RECRUITING, COMPLETED, TERMINATED, WITHDRAWN, SUSPENDED, ENROLLING_BY_INVITATION, UNKNOWN

Valid phases: EARLY_PHASE1, PHASE1, PHASE2, PHASE3, PHASE4, NA


search_turkey_trials

Convenience wrapper: search_trials with country="Turkey". Same parameters (minus country).


get_trial

Fetch full details for a single study.

Parameter Type Description
nct_id str NCT number, e.g. "NCT05678901"
force_refresh bool Skip cache

Returns: single normalized study with full eligibility.criteria_text and all locations.


Normalized Study Schema

Every tool returns studies in this flat schema:

{
  "nct_id": "NCT05678901",
  "title": "A Study of Sotorasib...",
  "status": "RECRUITING",
  "status_unknown_flag": false,
  "phases": ["PHASE2"],
  "study_type": "INTERVENTIONAL",
  "conditions": ["Non-Small Cell Lung Cancer"],
  "interventions": [{"type": "DRUG", "name": "Sotorasib"}],
  "eligibility": {
    "criteria_text": "Inclusion Criteria:\n- KRAS G12C...",
    "sex": "ALL",
    "min_age": "18 Years",
    "max_age": "N/A",
    "healthy_volunteers": false
  },
  "locations": [
    {"country": "Turkey", "city": "Istanbul", "facility": "IUH", "status": "RECRUITING"}
  ],
  "has_turkey_site": true,
  "turkey_sites": [{"city": "Istanbul", "facility": "IUH", "status": "RECRUITING"}],
  "lead_sponsor": "Amgen",
  "last_update_post_date": "2024-05-01",
  "url": "https://clinicaltrials.gov/study/NCT05678901",
  "retrieved_at": "2026-06-24T10:30:00+00:00",
  "freshness": "live",
  "cached_at": null
}

Key fields for clinicians:

  • status_unknown_flag: true → status unverified for 2+ years, verify before acting
  • retrieved_at → when data was fetched from CT.gov (always surface this)
  • freshness: "cached" → data served from local cache; cached_at shows when it was stored

OncoHub Integration: A1 → A2.3 Field Mapping

A1 Patient Profile Field dual_source_search Parameter Notes
Tumor type / primary diagnosis condition Required
Biomarker (e.g. KRAS G12C, PD-L1) term Free text, forwarded to query.term
Current/target drug intervention Forwarded to query.intr
Treatment line / phase preference phases e.g. ["PHASE2","PHASE3"]
Eligibility status filter statuses Default: RECRUITING + NOT_YET_RECRUITING

Module flow:

A1 Patient Card
    ↓
A2.3 dual_source_search(condition, term, intervention, phases)
    ↓
Normalized studies[] with has_turkey_site, freshness, retrieved_at
    ↓
A3 Eligibility Matrix
    ↓
A5 Council Report Output

The server provides data only. A3 performs eligibility matching; A5 formats the output.


Cache & Freshness Configuration

Variable Default Description
STATUS_TTL_DAYS 7 Max age for cached recruiting/status data
META_TTL_DAYS 30 Reserved for future eligibility-only caching
CACHE_PATH .cache/ctgov.db SQLite file path

Why TTL matters for patient safety: Trial status changes frequently. A "RECRUITING" status cached 30 days ago may no longer be accurate. STATUS_TTL_DAYS=7 ensures clinicians see data verified within one week, or the server fetches fresh data.

Cache behavior:

  • Hit (fresh): returns stored data with freshness: "cached" + cached_at timestamp
  • Miss or expired: fetches from CT.gov, updates cache, returns with freshness: "live"
  • force_refresh: true: always fetches live, updates cache

Cloud deployments: On free-tier hosts with ephemeral storage, the cache resets on each restart — all requests go live until the cache warms up again. Use a persistent volume for production.


Rate Limiting & CT.gov ToU Compliance

  • Minimum 1 second between API requests (CTGOV_RATE_INTERVAL=1.0)
  • Automatic exponential-backoff retry on network/5xx errors (max 3 attempts)
  • No contact-harvesting: email, phone, and investigator PII are never included in output
  • No bulk corpus download: pageSize capped at 50 per call
  • User-Agent header identifies this client to CT.gov

No Authentication Required

CT.gov v2 is a public API — no API key, no OAuth. This server also has no auth on its /mcp endpoint (it serves read-only public data). For production deployments where you want to restrict access, place a reverse proxy with IP allowlisting or a simple bearer token in front.

from github.com/baris-varis/Initial-CT-MSP-MCP-server

Установка ClinicalTrials.Gov Server — OncoHub

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/baris-varis/Initial-CT-MSP-MCP-server

FAQ

ClinicalTrials.Gov Server — OncoHub MCP бесплатный?

Да, ClinicalTrials.Gov Server — OncoHub MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для ClinicalTrials.Gov Server — OncoHub?

Нет, ClinicalTrials.Gov Server — OncoHub работает без API-ключей и переменных окружения.

ClinicalTrials.Gov Server — OncoHub — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить ClinicalTrials.Gov Server — OncoHub в Claude Desktop, Claude Code или Cursor?

Открой ClinicalTrials.Gov Server — OncoHub на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare ClinicalTrials.Gov Server — OncoHub with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development