Skip to main content
Glama

ClinicalTrials.gov MCP Server

studyRanking.ts3.36 kB
/** * @fileoverview Study ranking utilities for clinical trial matching. * Provides functions to calculate weights and rank studies based on * various criteria including phase, enrollment, and location relevance. * * @module src/mcp-server/tools/utils/studyRanking */ /** * Interface for a rankable study (must have match score, locations, and details). */ export interface RankableStudy { matchScore: number; locations: Array<{ distance?: number | undefined }>; studyDetails: { phase?: string[] | undefined; enrollmentCount?: number | undefined; }; } /** * Calculates a numeric weight for a study phase. * Higher phases (more advanced trials) receive higher weights. * * @param phases - Array of phase strings (e.g., ["Phase 3", "Phase 4"]) * @returns Numeric weight representing the highest phase (0-4) * * @example * getPhaseWeight(["Phase 3"]) // returns 3 * getPhaseWeight(["Phase 1", "Phase 2"]) // returns 2 (max) * getPhaseWeight(["N/A"]) // returns 0 * getPhaseWeight(undefined) // returns 0 */ export function getPhaseWeight(phases?: string[]): number { if (!phases || phases.length === 0) return 0; const phaseMap: Record<string, number> = { 'Phase 4': 4, 'Phase 3': 3, 'Phase 2': 2, 'Phase 1': 1, 'N/A': 0, 'Not Applicable': 0, }; // Return the maximum phase weight from the array return Math.max(...phases.map((p) => phaseMap[p] ?? 0)); } /** * Ranks an array of studies based on multiple criteria. * Sorting priority: matchScore → location count → phase → enrollment count. * * @param studies - Array of studies to rank * @returns Sorted array with highest-ranked studies first * * @example * rankStudies([study1, study2, study3]) * // returns studies sorted by relevance */ export function rankStudies<T extends RankableStudy>(studies: T[]): T[] { return [...studies].sort((a, b) => { // Primary: Match score (higher is better) if (a.matchScore !== b.matchScore) { return b.matchScore - a.matchScore; } // Secondary: Number of nearby locations (more is better) const aLocationCount = a.locations.length; const bLocationCount = b.locations.length; if (aLocationCount !== bLocationCount) { return bLocationCount - aLocationCount; } // Tertiary: Study phase (later phase = more established) const aPhase = getPhaseWeight(a.studyDetails.phase); const bPhase = getPhaseWeight(b.studyDetails.phase); if (aPhase !== bPhase) { return bPhase - aPhase; } // Quaternary: Enrollment count (higher = more capacity) const aEnrollment = a.studyDetails.enrollmentCount ?? 0; const bEnrollment = b.studyDetails.enrollmentCount ?? 0; return bEnrollment - aEnrollment; }); } /** * Calculates a match score based on eligibility checks. * Each successful check adds points to the total score. * * @param checks - Array of eligibility check results * @returns Total match score (0-100) * * @example * calculateMatchScore([ * { eligible: true }, * { eligible: true }, * { eligible: true }, * ]) * // returns 75 (3 checks × 25 points each) */ export function calculateMatchScore( checks: Array<{ eligible: boolean }>, ): number { const pointsPerCheck = 25; const passedChecks = checks.filter((c) => c.eligible).length; return passedChecks * pointsPerCheck; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/clinicaltrialsgov-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server