Skip to main content
Glama
agents100x

clinicaltrials-mcp

by agents100x
README.md
# clinicaltrials-mcp

**Conversational access to 400,000+ clinical trials — for pharma analysts, CRO teams, and health-tech builders.**

A Python MCP server that connects Cursor, Claude Desktop, and any MCP-compatible client directly to ClinicalTrials.gov. Ask questions in plain English. Get clean, structured answers in seconds — no API keys, no setup, no parsing raw JSON.

[![PyPI version](https://img.shields.io/pypi/v/clinicaltrials-mcp.svg)](https://pypi.org/project/clinicaltrials-mcp/)
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

---

## The Problem

ClinicalTrials.gov is the world's largest registry of clinical research — 400,000+ trials, decades of outcomes data, all publicly accessible via a free API.

But the API gives you this:

```json
{
  "protocolSection": {
    "eligibilityModule": {
      "eligibilityCriteria": "Inclusion Criteria:\n\n* Willing to sign the informed consent form;\n* ≥18 years old;\n* Diagnosed histologically or cytologically with local advanced or metastatic HER2-positive malignant solid cancer...",
      "stdAges": ["ADULT", "OLDER_ADULT"]
    },
    "adverseEventsModule": {
      "eventGroups": [...],
      "seriousEvents": [...],
      "otherEvents": [...]
    }
  }
}
```

Every field is optional. Eligibility criteria are a single wall of free text. Adverse events are split across two arrays that reference a separate groups table by ID. Every trial returns a different shape.

To compare eligibility across 10 trials, you write 10 scripts — or spend two days copying into Excel. To find the adverse event profile of a completed study, you navigate five nested objects and cross-reference three tables. To do a competitive landscape analysis across a therapeutic area, you're looking at a week of work.

**This is not a data problem. It is a tooling problem.**

With clinicaltrials-mcp, the same work takes a conversation:

> *"Compare the eligibility criteria for these 5 NASH trials"*
> *"What were the Grade 3+ adverse events in NCT02142803?"*
> *"Find recruiting HER2-positive trials near Mumbai"*

Seconds. Followed up. Drilled down. No scripts, no parsing, no Excel.

---

## Install & Setup

### Step 1 — Install

```bash
pip install clinicaltrials-mcp
```

No API key. No account. No configuration required.

### Step 2 — Add to your MCP client

```json
{
  "mcpServers": {
    "clinicaltrials": {
      "command": "uvx",
      "args": ["clinicaltrials-mcp"]
    }
  }
}
```

`uvx` runs the package without requiring it on your `$PATH`. If you don't have `uv`: `pip install uv`.

Restart your MCP client. The 5 tools appear automatically.

---

### Running from source (contributors / developers)

```bash
git clone https://github.com/agents100x/clinicaltrials-mcp
cd clinicaltrials-mcp
uv sync
```

```json
{
  "mcpServers": {
    "clinicaltrials": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/path/to/clinicaltrials-mcp",
        "clinicaltrials-mcp"
      ]
    }
  }
}
```

---

### Where is the config file?

| Client | Config file location |
|---|---|
| **Claude Desktop** (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| **Claude Desktop** (Windows) | `%APPDATA%\Claude\claude_desktop_config.json` |
| **Cursor** | `.cursor/mcp.json` or Settings → MCP |
| **VS Code / forks** | Settings → MCP Servers → Edit config |

Restart the client after saving. The 5 tools appear automatically.

---

## Sample Queries

Organised by real analyst workflows. All queries work in plain English — no syntax required.

---

### Competitive Intelligence

```
"Show me recruiting Phase III trials for breast cancer"
"Find all active Phase II Alzheimer's trials in Europe"
"What NASH trials completed in the last 2 years?"
"Are there any recruiting trials for KRAS-mutant lung cancer?"
"Show me TERMINATED trials for diabetes — I want to know what failed"
```

The last query uses the status override: *"...status='TERMINATED'"* — WITHDRAWN and TERMINATED
trials are excluded by default, but you can always ask for them explicitly.

---

### Patient Eligibility & Site Feasibility (CRO Teams)

```
"Get the full eligibility criteria for NCT04280341"
"Find recruiting HER2-positive breast cancer trials near Mumbai, India"
"Find Type 2 Diabetes trials recruiting near Bangalore, India"
"Are there any recruiting immunotherapy trials near London?"
```

> **Note on site status:** Results are filtered by overall trial status. Always verify
> the specific site's recruitment status at clinicaltrials.gov before contacting a site.

---

### Protocol Comparison (Medical Writers / Researchers)

```
"Compare NCT04280341 and NCT02142803 on eligibility criteria"
"Compare the design and timeline of NCT04280341 and NCT03817944"
"Compare the endpoints of these three pembrolizumab trials: NCT04280341, NCT03817944, NCT02142803"
```

Focus the comparison with `compare_on`:
- `"...compare on design"` — phase, randomisation, blinding, arms
- `"...compare on eligibility"` — inclusion/exclusion criteria side by side
- `"...compare on endpoints"` — primary and secondary outcomes
- `"...compare on timeline"` — start dates, completion dates, enrollment targets
- `"...compare on locations"` — countries and site counts

---

### Results & Safety Review

```
"What were the adverse events reported in NCT02142803?"
"Show me all Grade 1 and above adverse events for NCT02142803"
"Give me a quick summary of the primary outcome of NCT02142803"
"What were the participant flow and dropout reasons in NCT02142803?"
```

Results options:
- Default shows **serious adverse events only** (Grade 3+)
- *"...include all grades"* → adds Grade 1/2 events
- *"...summary only"* → returns just the primary outcome in 2–3 lines, useful for scanning many trials

---

### Edge Cases the Tool Handles Cleanly

```
"Get results for NCT03444521"
→ Returns: "Trial completed in 2022 but no results posted — this is common,
   ~60% of completed trials never post results. It does not mean the trial failed."

"Find recruiting trials for Niemann-Pick disease near Paris"
→ Returns: helpful no-results message with suggestions to broaden the search

"Find terminated trials for a condition"
→ Requires explicit status override — the tool tells you exactly how
```

---

## The 5 Tools

| Tool | What It Does | Key Design Decision |
|---|---|---|
| `search_trials` | Search by condition, phase, status, location | WITHDRAWN + TERMINATED excluded by default — always explained, always overridable |
| `get_trial_details` | Full structured summary by NCT ID | Eligibility always verbatim — never paraphrased |
| `compare_trials` | Side-by-side comparison of 2–5 trials | `compare_on` param: all, design, eligibility, endpoints, timeline, locations |
| `get_trial_results` | Outcomes, AEs, participant flow | AE grade note top + bottom; 4-case no-results handling |
| `find_recruiting_near` | Recruiting trials near a location | City → country location rings, honest about CT.gov's city-level data |

---

## Why This Is Different

Every other ClinicalTrials.gov MCP passes raw JSON from the API to the LLM and calls it done.

This is a **workflow tool**, not an API wrapper:

- **Outputs designed around what analysts do** — not what the API can return
- **Opinionated defaults** — RECRUITING sorts first, Grade 3+ AEs shown, status filter always explained
- **Honest about data gaps** — ~60% of completed trials never post results; we say so every time
- **Verbatim eligibility criteria** — never paraphrased, too risky to interpret clinical text
- **Verification by design** — NCT hyperlinks appear at the top and bottom of every trial detail

---

## Limitations

- Data is self-reported by sponsors on ClinicalTrials.gov — not independently verified by us
- ~60% of completed trials have no posted results on CT.gov
- Trial status and site data may lag real-world updates by weeks
- Location filtering is city/country level — no GPS radius search available
- Not all trials in the world are registered on CT.gov

**Data returned by this tool should never be used directly in regulatory submissions,
publications, or clinical decisions without independent verification at clinicaltrials.gov.**

Full scope and data disclaimer: [DISCLAIMER.md](DISCLAIMER.md)

---

## How It Works

```
Claude or Cursor
      |
      | MCP tool call over stdio
      |
  server.py      — registers 5 tools, routes calls, catches all errors gracefully
      |
  client.py      — async httpx client for CT.gov API v2 (public, no auth required)
      |
  ClinicalTrials.gov  — public REST API, 400,000+ registered trials
      |
  formatters.py  — transforms raw JSON into clean, structured markdown
      |
Claude or Cursor — reads formatted output and responds to the user
```

**Stack:** Python 3.12+ · [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) · [httpx](https://www.python-httpx.org/) · [uv](https://github.com/astral-sh/uv)

---

## Contributing

```bash
git clone https://github.com/agents100x/clinicaltrials-mcp
cd clinicaltrials-mcp
uv sync
uv run pytest tests/ -m "not integration"   # offline unit tests, ~0.3s
uv run pytest tests/                         # full suite including live API
```

Bug reports and pull requests welcome at
[github.com/agents100x/clinicaltrials-mcp/issues](https://github.com/agents100x/clinicaltrials-mcp/issues).

---

## License

MIT — see [LICENSE](LICENSE) for details.

Built by [agents100x](https://github.com/agents100x).

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: searching, getting details, getting results, comparing, and finding recruiting trials by location. No overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (e.g., search_trials, get_trial_details) using underscores, making them predictable and easy to understand.

Tool Count5/5

5 tools cover the essential operations for clinical trials access without being excessive or insufficient, making the server well-scoped.

Completeness4/5

The set covers searching, details, results, comparison, and location-based filtering. Minor gaps like advanced filters or site-specific status do not hinder primary workflows.

Maintenance

ActivityInactive
ResponsivenessUnresponsive