clinicaltrialsgov-mcp-server
Version:
Search ClinicalTrials.gov trials, retrieve study details and results, and match patients to eligible trials via MCP. STDIO or Streamable HTTP.
71 lines • 3.49 kB
TypeScript
/**
* @fileoverview Match patient demographics to eligible recruiting clinical trials.
* @module mcp-server/tools/definitions/find-eligible.tool
*/
import { z } from '@cyanheads/mcp-ts-core';
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
/**
* Score how directly a study's own listed conditions match the patient's
* requested conditions. ClinicalTrials.gov's `query.cond` is a fuzzy relevance
* search that pulls in tangential trials via the MeSH umbrella (e.g. a Von
* Willebrand bleeding-disorder trial matches "Cardiovascular Disease" through a
* distant MeSH ancestor). This score re-ranks those tangential matches below
* trials whose own condition list actually names a requested condition — a
* transparent, deterministic rule, not a relevance estimate. Recall is
* unchanged: every upstream match is still returned, only reordered.
*
* Tiers (best across the study's conditions × requested conditions):
* 3 — exact match (study condition equals a requested condition)
* 2 — every significant token of a multi-word requested condition is present
* in a study condition, so the study names the same concept or a more
* specific subtype — independent of word order ("Type 2 Diabetes" matches
* both "Type 2 Diabetes Mellitus" and "Diabetes Mellitus, Type 2";
* "Cardiovascular Disease" matches "Atherosclerotic Cardiovascular
* Disease"). Gated to multi-word requests so a single word like
* "Hypertension" does not credit the distinct disease "Pulmonary Arterial
* Hypertension" as a subtype — it falls to tier 1, below a genuine
* "Hypertension" exact match at tier 3.
* 1 — a shared significant token ("Type 2 Diabetes" ↔ "Diabetes Mellitus")
* 0 — no direct overlap (matched only through upstream fuzziness)
*/
export declare function conditionMatchScore(studyConditions: string[], requested: string[]): number;
export declare const findEligible: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
age: z.ZodNumber;
sex: z.ZodEnum<{
FEMALE: "FEMALE";
MALE: "MALE";
ALL: "ALL";
}>;
conditions: z.ZodArray<z.ZodString>;
location: z.ZodObject<{
country: z.ZodString;
state: z.ZodOptional<z.ZodString>;
city: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;
healthyVolunteer: z.ZodDefault<z.ZodBoolean>;
recruitingOnly: z.ZodDefault<z.ZodBoolean>;
maxResults: z.ZodDefault<z.ZodNumber>;
}, z.core.$strip>, z.ZodObject<{
studies: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
totalCount: z.ZodOptional<z.ZodNumber>;
}, z.core.$strip>, readonly [{
readonly reason: "rate_limited";
readonly code: JsonRpcErrorCode.RateLimited;
readonly when: "ClinicalTrials.gov returned 429 after retry budget exhausted.";
readonly recovery: "ClinicalTrials.gov rate-limited the request after several retries; wait about a minute before trying again.";
readonly retryable: true;
}], {
readonly searchCriteria: z.ZodObject<{
conditions: z.ZodArray<z.ZodString>;
location: z.ZodString;
age: z.ZodNumber;
sex: z.ZodString;
}, z.core.$strip>;
readonly funnel: z.ZodObject<{
conditionMatched: z.ZodNumber;
locationMatched: z.ZodNumber;
demographicsMatched: z.ZodNumber;
}, z.core.$strip>;
readonly notice: z.ZodOptional<z.ZodString>;
}>;
//# sourceMappingURL=find-eligible.tool.d.ts.map