# mcp/clinicaltrials.py import httpx from typing import List, Dict BASE_V2 = "https://clinicaltrials.gov/api/v2/studies" BASE_V1 = "https://clinicaltrials.gov/api/query/study_fields" HEADERS = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0 Safari/537.36" ) } async def fetch_trials_v2(term: str, limit: int = 10) -> List[Dict]: """Fetch clinical trials using v2 API.""" params = { "query": term, "pageSize": limit, "fields": "nctId,briefTitle,phase,status,startDate,conditions,interventions" } async with httpx.AsyncClient(timeout=20, headers=HEADERS) as client: r = await client.get(BASE_V2, params=params) if r.status_code == 403: return [] # API blocked or IP rate-limited r.raise_for_status() js = r.json() # List of studies under ['studies'] return js.get("studies", []) async def fetch_trials_v1(term: str, limit: int = 10) -> List[Dict]: """Fallback: Fetch trials using legacy v1 API.""" params = dict( expr=term, fields="NCTId,BriefTitle,Condition,InterventionName,Phase,OverallStatus,StartDate", max_rnk=limit, min_rnk=1, fmt="json", ) async with httpx.AsyncClient(timeout=20, headers=HEADERS) as client: r = await client.get(BASE_V1, params=params) if r.status_code == 403: return [] r.raise_for_status() js = r.json() return js.get("StudyFieldsResponse", {}).get("StudyFields", []) async def search_trials(term: str, max_studies: int = 10) -> List[Dict]: """Unified entry point. Try V2, fallback to V1 if needed.""" try: trials = await fetch_trials_v2(term, max_studies) if trials: return trials except Exception: pass try: trials = await fetch_trials_v1(term, max_studies) return trials except Exception: return []