| summary | Fix format() drop-offs across 4 tools; fall back to per-ID calls when batch rejects on a single bad NCT |
|---|---|
| breaking | false |
analyze_trial_landscapeprompt —focusAreasargument unusable — The arg was declared asz.array(z.string()), but per the MCP spec,prompts/getsendsargumentsasRecord<string, string>with no wire format for arrays. Sending an array failed protocol-layer validation; sending a comma-string failed the tool-layer schema. ChangedfocusAreasto a comma-separatedz.string();generate()splits on,, trims, and filters. Verified via HTTP:"phases, sponsors"now producesFocus the analysis on: **phases, sponsors**. Closes #27.clinicaltrials_get_study_record—format()still droppedhasResults,resultsSection,derivedSection,documentSection— Follow-up to #18. Added four render blocks:**Has Results:**with a pointer toclinicaltrials_get_study_resultswhen true;**MeSH Conditions:**and**MeSH Interventions:**fromderivedSection.*BrowseModule(prefersbrowseLeaves, falls back tomeshes); a## Results Summarystub with counts for outcome measures, adverse events, participant-flow periods, and baseline measures; a## Documents (N)section with kind tags (Protocol/SAP/ICF) and upload dates fromdocumentSection.largeDocumentModule.largeDocs. ExtendedRawStudyShapewithdocumentSectionandbrowseLeaves. Verified live on NCT03722472 (renders all four) and NCT02194738 (confirmsMeSH Interventionspath with 16 drug/procedure terms). Closes #28.clinicaltrials_get_field_values—format()silently dropped up to 235 values — Hard.slice(0, 15)ontopValueswith no tail message.structuredContentcarried up to 250 values, butcontent[]consumers lost everything beyond the 15-value cap. Added an explicit tail:… and N more values in structuredContent (of X unique; topValues capped at 250). Documented the 250 cap in the output schema's.describe(). Verified onLeadSponsorName(49,996 unique values → 15 rendered + tail message). Closes #30.clinicaltrials_get_field_definitions—format()dropped fielddescription— The field tree'sdescriptionis the one place in the server's tool surface where authoritative data-model documentation lives, butformat()never read the property, so LLM-only clients lost the context. Added a<description>line beneath each field when present, for both top-level and nested renders. Verified onprotocolSection.identificationModule—nctIdnow renders its canonical description incontent[]. Closes #31.clinicaltrials_get_study_results— partial-invalid batch cascaded failure to valid NCTs — Follow-up to #23. The batch endpoint (filter.ids) rejects the whole request if any single ID is malformed or nonexistent, and the handler mapped that batch-wide error to every input ID — so a single bad ID dropped all valid results. Changed the catch block to fall back to sequential per-IDgetStudycalls (honors the service's ~1 req/sec rate limit); only truly failing IDs now land infetchErrors. AddederroredIdsSet to prevent the downstream missing-ID loop from double-counting fallback failures. Verified on[NCT03722472, NCT05956821, NCT00000000]: valid IDs succeed, onlyNCT00000000errors. Closes #32.
RawStudyShape— ExtendedderivedSection.conditionBrowseModuleandinterventionBrowseModulewithbrowseLeaves: Array<{ id?, name?, relevance? }>; added top-leveldocumentSection.largeDocumentModule.largeDocs: Array<{ filename?, hasIcf?, hasProtocol?, hasSap?, label?, typeAbbrev?, uploadDate? }>. All additive — no breaking changes.