#!/usr/bin/env node
import fetch from 'node-fetch';
import 'dotenv/config';
import http from 'http';
import { URLSearchParams } from "url";
import { Tool } from "./types";
import * as fs from 'fs';
import * as path from 'path';
import * as readline from 'readline';
import * as zlib from 'zlib';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* Logging utility for consistent log format across the application
*/
const logger = {
levels: {
error: 0,
warn: 1,
info: 2,
debug: 3
} as const,
level: (process.env.LOG_LEVEL || 'info') as LogLevel,
formatMessage: (level: string, message: string, meta?: any) => {
const timestamp = new Date().toISOString();
return JSON.stringify({ timestamp, level, message, ...meta });
},
error: (message: string, meta?: any) => {
if (logger.levels[logger.level as keyof typeof logger.levels] >= logger.levels.error) {
process.stderr.write(logger.formatMessage('error', message, meta) + '\n');
}
},
warn: (message: string, meta?: any) => {
if (logger.levels[logger.level as keyof typeof logger.levels] >= logger.levels.warn) {
process.stderr.write(logger.formatMessage('warn', message, meta) + '\n');
}
},
info: (message: string, meta?: any) => {
if (logger.levels[logger.level as keyof typeof logger.levels] >= logger.levels.info) {
if (!USE_HTTP) {
process.stderr.write(logger.formatMessage('info', message, meta) + '\n');
} else {
process.stdout.write(logger.formatMessage('info', message, meta) + '\n');
}
}
},
debug: (message: string, meta?: any) => {
if (logger.levels[logger.level as keyof typeof logger.levels] >= logger.levels.debug) {
if (!USE_HTTP) {
process.stderr.write(logger.formatMessage('debug', message, meta) + '\n');
} else {
process.stdout.write(logger.formatMessage('debug', message, meta) + '\n');
}
}
}
};
type LogLevel = 'error' | 'warn' | 'info' | 'debug';
// API configuration and environment variables
const USE_HTTP = process.env.USE_HTTP === 'true';
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000;
// CMS Medicare dataset version mapping for each dataset type
const versionMapGeography: { [year: string]: string } = {
"2023": "ddee9e22-7889-4bef-975a-7853e4cd0fbb",
"2022": "87304f15-9ed0-41dc-a141-6141a0327453",
"2021": "f00f462f-bb61-48b1-a321-1c50d78ce175",
"2020": "31eb3018-43e0-4259-a0d8-e7a1112ffd08",
"2019": "673030ae-ceed-4561-8fca-b1275395a86a",
"2018": "05a85700-052f-4509-af43-7042b9b35868",
"2017": "8e96a9f2-ce6e-46fd-b30d-8c695c756bfd",
"2016": "c7d3f18c-2f00-4553-8cd1-871b727d5cdd",
"2015": "dbee9609-2c90-43ca-b1b8-161bd9cfcdb2",
"2014": "28181bd2-b377-4003-b73a-4bd92d1db4a9",
"2013": "3c2a4756-0a8c-4e4d-845a-6ad169cb13d3"
};
const versionMapProviderAndService: { [year: string]: string } = {
"2023": "0e9f2f2b-7bf9-451a-912c-e02e654dd725",
"2022": "e650987d-01b7-4f09-b75e-b0b075afbf98",
"2021": "31dc2c47-f297-4948-bfb4-075e1bec3a02",
"2020": "c957b49e-1323-49e7-8678-c09da387551d",
"2019": "867b8ac7-ccb7-4cc9-873d-b24340d89e32",
"2018": "fb6d9fe8-38c1-4d24-83d4-0b7b291000b2",
"2017": "85bf3c9c-2244-490d-ad7d-c34e4c28f8ea",
"2016": "7918e22a-fbfb-4a07-9f59-f8aab2b757d4",
"2015": "f8cdb11a-d5f7-4fbe-aac4-05abc8ee2c83",
"2014": "f63b48ae-946e-48f7-9f56-327a68da4e0b",
"2013": "ad5e7548-98ab-4325-af4b-b2a7099b9351"
};
const versionMapProvider: { [year: string]: string } = {
"2023": "8889d81e-2ee7-448f-8713-f071038289b5",
"2022": "21555c17-ec1b-4e74-b2c6-925c6cbb3147",
"2021": "44e0a489-666c-4ea4-a1a2-360b6cdc19db",
"2020": "29d799aa-c660-44fe-a51a-72c4b3e661ac",
"2019": "6a53afe5-1cbc-4b33-9dc8-926ee532dc66",
"2018": "900850df-c9a9-47ce-a9e0-d0ceae5a811f",
"2017": "44ea2789-993f-4d55-ac44-ed7f160b58fa",
"2016": "2691839a-99fb-45a1-9bd9-86905ba975cc",
"2015": "fb870c06-27f2-4e15-b556-1731d794bb5b",
"2014": "100d9e00-03cd-4105-9f58-27f9bf9ab773",
"2013": "483a68df-26a9-42a5-a24c-7458e5374f61"
};
function getLatestYear(versionMap: { [year: string]: string }): string {
return Object.keys(versionMap).sort().pop()!;
}
export const MEDICARE_INFO_TOOL: Tool = {
name: "medicare_info",
description: "Unified tool for Medicare data operations: provider services, Part D prescribers, hospital data, spending information, hospital quality metrics, and ASP pricing. Use the method parameter to specify the operation type.",
input_schema: {
type: "object",
properties: {
method: {
type: "string",
description: "The operation to perform:\n" +
"- 'search_providers': Medicare Physician & Other Practitioners data\n" +
"- 'search_prescribers': Part D prescriber data\n" +
"- 'search_hospitals': Hospital utilization data\n" +
"- 'search_spending': Drug/service spending data\n" +
"- 'search_formulary': Part D formulary coverage\n" +
"- 'get_hospital_star_rating': Hospital overall quality star ratings (1-5)\n" +
"- 'get_readmission_rates': Hospital 30-day readmission rates by condition\n" +
"- 'get_hospital_infections': Hospital-acquired infections (HAI) data\n" +
"- 'get_mortality_rates': Hospital 30-day mortality rates\n" +
"- 'search_hospitals_by_quality': Find hospitals by quality metrics\n" +
"- 'compare_hospitals': Compare quality metrics across hospitals\n" +
"- 'get_vbp_scores': Hospital Value-Based Purchasing performance scores\n" +
"- 'get_hcahps_scores': Patient experience (HCAHPS) survey scores\n" +
"- 'get_asp_pricing': Medicare Part B ASP pricing data\n" +
"- 'get_asp_trend': ASP pricing trends over time\n" +
"- 'compare_asp_pricing': Compare ASP across drugs\n" +
"- 'get_formulary_trend': Track formulary changes over time (prior auth, tiers, coverage)"
},
dataset_type: {
type: "string",
description: "For search_providers: Type of dataset to search. Options:\n" +
"- 'geography_and_service': Use when you need to compare regions, analyze geographic patterns, study regional variations in healthcare delivery, understand geographic distribution of healthcare services, or calculate per-capita/per-beneficiary rates by region.\n" +
"- 'provider_and_service': Use when you need to analyze individual provider performance, track specific procedures by provider, calculate total procedures across providers, or study provider-level service patterns and outcomes.\n" +
"- 'provider': Use when you need to analyze provider demographics, study provider participation in Medicare, understand provider practice patterns, or examine provider-level beneficiary characteristics and risk scores."
},
year: {
type: "string",
description: "For search_providers: Year of the dataset to query (2013 to latest available year, defaults to latest year)."
},
hcpcs_code: {
type: "string",
description: "For search_providers: HCPCS code to search for (e.g., '99213' for established patient office visit)."
},
provider_type: {
type: "string",
description: "For search_providers: Type of provider to search for (e.g., 'Cardiology', 'Podiatry', 'Family Practice')."
},
geo_level: {
type: "string",
description: "For search_providers: Geographic level for filtering (e.g., 'National', 'State', 'County', 'ZIP')."
},
geo_code: {
type: "string",
description: "For search_providers: Geographic code to filter by (e.g., 'CA' for California, '06037' for Los Angeles County)."
},
place_of_service: {
type: "string",
description: "For search_providers: Place of service code to filter by (e.g., 'F' for facility, 'O' for office, 'H' for hospital)."
},
size: {
type: "number",
description: "Number of results to return (default: 10 for search_providers, 25 for search_formulary, max: 5000)."
},
offset: {
type: "number",
description: "Starting result number for pagination (default: 0)."
},
sort_by: {
type: "string",
description: "For search_providers: Field to sort results by (e.g., 'Tot_Srvcs', 'Tot_Benes', 'Tot_Mdcr_Pymt_Amt')."
},
sort_order: {
type: "string",
description: "For search_providers: Sort order ('asc' or 'desc', default: 'desc')."
},
drug_name: {
type: "string",
description: "For search_prescribers: Drug name to search for - brand or generic (e.g., 'semaglutide', 'Ozempic', 'metformin'). Searches both brand and generic names."
},
prescriber_type: {
type: "string",
description: "For search_prescribers: Prescriber specialty (e.g., 'Endocrinology', 'Family Practice', 'Internal Medicine')."
},
prescriber_npi: {
type: "string",
description: "For search_prescribers: National Provider Identifier (NPI) of the prescriber."
},
state: {
type: "string",
description: "For search_prescribers, search_hospitals: State abbreviation (e.g., 'CA', 'TX', 'NY')."
},
hospital_name: {
type: "string",
description: "For search_hospitals: Hospital name (partial match supported)."
},
hospital_id: {
type: "string",
description: "For search_hospitals: CMS Certification Number (CCN) or provider ID."
},
drg_code: {
type: "string",
description: "For search_hospitals (inpatient): Diagnosis Related Group (DRG) code."
},
spending_drug_name: {
type: "string",
description: "For search_spending: Drug name for spending analysis (brand or generic)."
},
spending_type: {
type: "string",
description: "For search_spending: Type of spending data - 'part_d' (prescription drugs), 'part_b' (administered drugs). Default: 'part_d'."
},
formulary_drug_name: {
type: "string",
description: "For search_formulary: Drug name to search for (partial match supported, e.g., 'metformin', 'insulin'). At least one of formulary_drug_name or ndc_code is required."
},
ndc_code: {
type: "string",
description: "For search_formulary: NDC (National Drug Code) for exact drug identification (e.g., '00002143380'). At least one of drug_name or ndc_code is required."
},
tier: {
type: "number",
description: "For search_formulary: Tier number to filter by (1=Preferred Generic, 2=Generic, 3=Preferred Brand, 4=Non-Preferred Brand, 5=Specialty, 6=Select Care)."
},
requires_prior_auth: {
type: "boolean",
description: "For search_formulary: Filter by prior authorization requirement (true=requires PA, false=no PA required)."
},
has_quantity_limit: {
type: "boolean",
description: "For search_formulary: Filter by quantity limit (true=has limit, false=no limit)."
},
has_step_therapy: {
type: "boolean",
description: "For search_formulary: Filter by step therapy requirement (true=requires ST, false=no ST required)."
},
plan_state: {
type: "string",
description: "For search_formulary: State abbreviation to filter plans (e.g., 'CA', 'TX', 'NY')."
},
plan_id: {
type: "string",
description: "For search_formulary: Medicare Part D plan ID to filter by specific plan."
},
quality_hospital_id: {
type: "string",
description: "For hospital quality methods: CMS Certification Number (CCN) to lookup specific hospital (e.g., '050146')."
},
quality_state: {
type: "string",
description: "For hospital quality methods: State abbreviation to filter hospitals (e.g., 'CA', 'TX', 'NY')."
},
min_star_rating: {
type: "number",
description: "For search_hospitals_by_quality: Minimum star rating (1-5) to filter hospitals."
},
condition: {
type: "string",
description: "For get_readmission_rates/get_mortality_rates: Medical condition to filter by (e.g., 'heart_failure', 'pneumonia', 'heart_attack', 'copd', 'stroke')."
},
infection_type: {
type: "string",
description: "For get_hospital_infections: Type of infection (e.g., 'CLABSI', 'CAUTI', 'SSI', 'CDIFF', 'MRSA')."
},
metrics: {
type: "array",
description: "For compare_hospitals: Array of metrics to compare (e.g., ['star_rating', 'readmission_rate', 'mortality_rate', 'infection_rate'])."
},
hospital_ids: {
type: "array",
description: "For compare_hospitals: Array of hospital CCN IDs to compare."
},
hcpcs_code_asp: {
type: "string",
description: "For ASP pricing methods: HCPCS code for Part B drug (e.g., 'J9035' for Bevacizumab)."
},
quarter: {
type: "string",
description: "For get_asp_pricing: Quarter for ASP data (e.g., '2025Q1', '2024Q4')."
},
start_quarter: {
type: "string",
description: "For get_asp_trend: Starting quarter for trend analysis (e.g., '2023Q1')."
},
end_quarter: {
type: "string",
description: "For get_asp_trend: Ending quarter for trend analysis (e.g., '2025Q1')."
},
hcpcs_codes: {
type: "array",
description: "For compare_asp_pricing: Array of HCPCS codes to compare pricing."
},
hcahps_measure: {
type: "string",
description: "For get_hcahps_scores: HCAHPS measure ID to filter by (e.g., 'H_COMP_1_A_P' for nurse communication, 'H_HSP_RATING_9_10' for hospital rating 9-10)."
},
vbp_domain: {
type: "string",
description: "For get_vbp_scores: VBP domain to filter by ('clinical_outcomes', 'person_community_engagement', 'safety', 'efficiency_cost_reduction', or 'all' for total performance score)."
},
start_month: {
type: "string",
description: "For get_formulary_trend: Starting month in YYYYMM format (e.g., '202401' for January 2024)."
},
end_month: {
type: "string",
description: "For get_formulary_trend: Ending month in YYYYMM format (e.g., '202512' for December 2025)."
},
trend_metric: {
type: "string",
description: "For get_formulary_trend: Metric to track ('prior_auth', 'tier', 'quantity_limit', 'coverage', or 'all'). Default: 'all'."
}
},
required: ["method"]
},
responseSchema: {
type: "object",
properties: {
total: {
type: "number",
description: "Total number of results found"
},
providers: {
type: "array",
description: "List of Medicare providers matching the search criteria",
items: {
type: "object",
properties: {
npi: { type: "string", description: "Provider's National Provider Identifier (NPI)" },
provider_name: { type: "string", description: "Provider's full name" },
provider_type: { type: "string", description: "Provider's specialty or type of practice" },
provider_address: { type: "string", description: "Provider's street address" },
provider_city: { type: "string", description: "Provider's city" },
provider_state: { type: "string", description: "Provider's state (2-letter abbreviation)" },
provider_zip: { type: "string", description: "Provider's ZIP code" },
provider_country: { type: "string", description: "Provider's country code (typically 'US')" },
medicare_participating: { type: "string", description: "Whether the provider participates in Medicare ('Y' for yes, 'N' for no)" },
total_hcpcs_codes: { type: "number", description: "Total number of unique HCPCS codes used by the provider" },
total_beneficiaries: { type: "number", description: "Total number of unique Medicare beneficiaries served" },
total_services: { type: "number", description: "Total number of services provided" },
total_submitted_charges: { type: "number", description: "Total amount of submitted charges in dollars" },
total_medicare_allowed: { type: "number", description: "Total amount allowed by Medicare in dollars" },
total_medicare_payment: { type: "number", description: "Total amount paid by Medicare in dollars" },
total_medicare_standardized: { type: "number", description: "Total standardized Medicare payment amount in dollars (adjusted for geographic differences)" },
beneficiary_average_age: { type: "number", description: "Average age of beneficiaries served" },
beneficiary_age_lt_65: { type: "number", description: "Number of beneficiaries under 65 years old" },
beneficiary_age_65_74: { type: "number", description: "Number of beneficiaries aged 65-74" },
beneficiary_age_75_84: { type: "number", description: "Number of beneficiaries aged 75-84" },
beneficiary_age_gt_84: { type: "number", description: "Number of beneficiaries over 84 years old" },
beneficiary_female_count: { type: "number", description: "Number of female beneficiaries" },
beneficiary_male_count: { type: "number", description: "Number of male beneficiaries" },
beneficiary_race_white: { type: "number", description: "Number of white beneficiaries" },
beneficiary_race_black: { type: "number", description: "Number of black beneficiaries" },
beneficiary_race_api: { type: "number", description: "Number of Asian/Pacific Islander beneficiaries" },
beneficiary_race_hispanic: { type: "number", description: "Number of Hispanic beneficiaries" },
beneficiary_race_native: { type: "number", description: "Number of Native American beneficiaries" },
beneficiary_race_other: { type: "number", description: "Number of beneficiaries of other races" },
beneficiary_dual_count: { type: "number", description: "Number of dual-eligible beneficiaries (eligible for both Medicare and Medicaid)" },
beneficiary_non_dual_count: { type: "number", description: "Number of non-dual-eligible beneficiaries" },
beneficiary_average_risk_score: { type: "number", description: "Average risk score of beneficiaries (higher scores indicate more complex medical conditions)" }
}
}
}
}
},
examples: [
{
name: 'Search for office visit codes by state (2023 data)',
description: 'Search for office visit codes by state (2023 data)',
input: { "dataset_type": "geography_and_service", "year": "2023", "hcpcs_code": "99213", "geo_level": "State", "geo_code": "CA", "size": 5, "sort_by": "Tot_Srvcs", "sort_order": "desc" },
output: { "total": 5, "providers": [{ "npi": "1234567890", "provider_name": "Dr. Jane Smith", "provider_type": "Family Practice", "provider_address": "789 Health St", "provider_city": "Los Angeles", "provider_state": "CA", "provider_zip": "90001", "provider_country": "US", "medicare_participating": "Y", "total_hcpcs_codes": 10, "total_beneficiaries": 100, "total_services": 500, "total_submitted_charges": 50000, "total_medicare_allowed": 40000, "total_medicare_payment": 35000, "total_medicare_standardized": 34000, "beneficiary_average_age": 70, "beneficiary_age_lt_65": 20, "beneficiary_age_65_74": 30, "beneficiary_age_75_84": 25, "beneficiary_age_gt_84": 25, "beneficiary_female_count": 55, "beneficiary_male_count": 45, "beneficiary_race_white": 60, "beneficiary_race_black": 10, "beneficiary_race_api": 15, "beneficiary_race_hispanic": 10, "beneficiary_race_native": 2, "beneficiary_race_other": 3, "beneficiary_dual_count": 15, "beneficiary_non_dual_count": 85, "beneficiary_average_risk_score": 1.2 }] }
},
{
name: 'Search for providers by specialty with pagination',
description: 'Search for providers by specialty with pagination',
input: { "dataset_type": "provider", "provider_type": "Podiatry", "geo_level": "State", "geo_code": "NY", "size": 10, "offset": 20, "sort_by": "Tot_Mdcr_Pymt_Amt", "sort_order": "desc" },
output: { "total": 10, "providers": [{ "npi": "0987654321", "provider_name": "Dr. John Doe", "provider_type": "Podiatry", "provider_address": "123 Foot Ave", "provider_city": "New York", "provider_state": "NY", "provider_zip": "10001", "provider_country": "US", "medicare_participating": "Y", "total_hcpcs_codes": 8, "total_beneficiaries": 80, "total_services": 400, "total_submitted_charges": 40000, "total_medicare_allowed": 32000, "total_medicare_payment": 28000, "total_medicare_standardized": 27000, "beneficiary_average_age": 65, "beneficiary_age_lt_65": 15, "beneficiary_age_65_74": 25, "beneficiary_age_75_84": 20, "beneficiary_age_gt_84": 20, "beneficiary_female_count": 45, "beneficiary_male_count": 35, "beneficiary_race_white": 50, "beneficiary_race_black": 8, "beneficiary_race_api": 12, "beneficiary_race_hispanic": 8, "beneficiary_race_native": 1, "beneficiary_race_other": 1, "beneficiary_dual_count": 10, "beneficiary_non_dual_count": 70, "beneficiary_average_risk_score": 1.1 }] }
},
{
name: 'Search for specific procedure by place of service',
description: 'Search for specific procedure by place of service',
input: { "dataset_type": "provider_and_service", "hcpcs_code": "45378", "place_of_service": "O", "size": 5, "sort_by": "Tot_Srvcs", "sort_order": "desc" },
output: { "total": 5, "providers": [{ "npi": "1122334455", "provider_name": "Dr. Alice Johnson", "provider_type": "Gastroenterology", "provider_address": "456 Digestive Blvd", "provider_city": "Chicago", "provider_state": "IL", "provider_zip": "60601", "provider_country": "US", "medicare_participating": "Y", "total_hcpcs_codes": 12, "total_beneficiaries": 120, "total_services": 600, "total_submitted_charges": 60000, "total_medicare_allowed": 48000, "total_medicare_payment": 42000, "total_medicare_standardized": 41000, "beneficiary_average_age": 68, "beneficiary_age_lt_65": 25, "beneficiary_age_65_74": 35, "beneficiary_age_75_84": 30, "beneficiary_age_gt_84": 30, "beneficiary_female_count": 60, "beneficiary_male_count": 60, "beneficiary_race_white": 70, "beneficiary_race_black": 15, "beneficiary_race_api": 20, "beneficiary_race_hispanic": 15, "beneficiary_race_native": 3, "beneficiary_race_other": 3, "beneficiary_dual_count": 20, "beneficiary_non_dual_count": 100, "beneficiary_average_risk_score": 1.3 }] }
},
{
name: 'Get total knee replacement procedures in California (2023)',
description: 'Search for all providers performing knee replacements (HCPCS 27447) in California, sorted by total services to get the top 100 providers',
input: { "dataset_type": "provider_and_service", "year": "2023", "hcpcs_code": "27447", "geo_level": "State", "geo_code": "CA", "size": 100, "sort_by": "Tot_Srvcs", "sort_order": "desc" },
output: { "total": 100, "providers": [{ "npi": "1234567890", "provider_name": "Dr. John Smith", "provider_type": "Orthopedic Surgery", "provider_address": "123 Medical Center Dr", "provider_city": "Los Angeles", "provider_state": "CA", "provider_zip": "90024", "provider_country": "US", "medicare_participating": "Y", "total_hcpcs_codes": 15, "total_beneficiaries": 95, "total_services": 120, "total_submitted_charges": 1200000, "total_medicare_allowed": 960000, "total_medicare_payment": 840000, "total_medicare_standardized": 820000, "beneficiary_average_age": 72, "beneficiary_age_lt_65": 15, "beneficiary_age_65_74": 35, "beneficiary_age_75_84": 30, "beneficiary_age_gt_84": 20, "beneficiary_female_count": 65, "beneficiary_male_count": 30, "beneficiary_race_white": 70, "beneficiary_race_black": 5, "beneficiary_race_api": 10, "beneficiary_race_hispanic": 10, "beneficiary_race_native": 1, "beneficiary_race_other": 4, "beneficiary_dual_count": 10, "beneficiary_non_dual_count": 85, "beneficiary_average_risk_score": 1.2 }], "total_services": 4958 }
}
]
};
interface MedicareProviderGeographyResponse {
Rndrng_Prvdr_Geo_Lvl: string;
Rndrng_Prvdr_Geo_Cd: string;
Rndrng_Prvdr_Geo_Desc: string;
HCPCS_Cd: string;
HCPCS_Desc: string;
HCPCS_Drug_Ind: string;
Place_Of_Srvc: string;
Tot_Rndrng_Prvdrs: number;
Tot_Benes: number;
Tot_Srvcs: number;
Tot_Bene_Day_Srvcs: number;
Avg_Sbmtd_Chrg: number;
Avg_Mdcr_Alowd_Amt: number;
Avg_Mdcr_Pymt_Amt: number;
Avg_Mdcr_Stdzd_Amt: number;
}
interface MedicareProviderIndividualResponse {
Rndrng_NPI: string;
Rndrng_Prvdr_Last_Org_Name: string;
Rndrng_Prvdr_First_Name: string;
Rndrng_Prvdr_MI: string;
Rndrng_Prvdr_Crdntls: string;
Rndrng_Prvdr_Ent_Cd: string;
Rndrng_Prvdr_St1: string;
Rndrng_Prvdr_St2: string;
Rndrng_Prvdr_City: string;
Rndrng_Prvdr_State_Abrvtn: string;
Rndrng_Prvdr_State_FIPS: string;
Rndrng_Prvdr_Zip5: string;
Rndrng_Prvdr_RUCA: string;
Rndrng_Prvdr_RUCA_Desc: string;
Rndrng_Prvdr_Cntry: string;
Rndrng_Prvdr_Type: string;
Rndrng_Prvdr_Mdcr_Prtcptg_Ind: string;
HCPCS_Cd: string;
HCPCS_Desc: string;
HCPCS_Drug_Ind: string;
Place_Of_Srvc: string;
Tot_Benes: number;
Tot_Srvcs: number;
Tot_Bene_Day_Srvcs: number;
Avg_Sbmtd_Chrg: number;
Avg_Mdcr_Alowd_Amt: number;
Avg_Mdcr_Pymt_Amt: number;
Avg_Mdcr_Stdzd_Amt: number;
}
interface MedicareProviderResponse {
Rndrng_NPI: string;
Rndrng_Prvdr_Last_Org_Name: string;
Rndrng_Prvdr_First_Name: string;
Rndrng_Prvdr_MI: string;
Rndrng_Prvdr_Crdntls: string;
Rndrng_Prvdr_Ent_Cd: string;
Rndrng_Prvdr_St1: string;
Rndrng_Prvdr_St2: string;
Rndrng_Prvdr_City: string;
Rndrng_Prvdr_State_Abrvtn: string;
Rndrng_Prvdr_State_FIPS: string;
Rndrng_Prvdr_Zip5: string;
Rndrng_Prvdr_RUCA: string;
Rndrng_Prvdr_RUCA_Desc: string;
Rndrng_Prvdr_Cntry: string;
Rndrng_Prvdr_Type: string;
Rndrng_Prvdr_Mdcr_Prtcptg_Ind: string;
Tot_HCPCS_Cds: string;
Tot_Benes: number;
Tot_Srvcs: number;
Tot_Sbmtd_Chrg: number;
Tot_Mdcr_Alowd_Amt: number;
Tot_Mdcr_Pymt_Amt: number;
Tot_Mdcr_Stdzd_Amt: number;
Bene_Avg_Age: number;
Bene_Age_LT_65_Cnt: number;
Bene_Age_65_74_Cnt: number;
Bene_Age_75_84_Cnt: number;
Bene_Age_GT_84_Cnt: number;
Bene_Feml_Cnt: number;
Bene_Male_Cnt: number;
Bene_Race_Wht_Cnt: number;
Bene_Race_Black_Cnt: number;
Bene_Race_API_Cnt: number;
Bene_Race_Hspnc_Cnt: number;
Bene_Race_NatInd_Cnt: number;
Bene_Race_Othr_Cnt: number;
Bene_Dual_Cnt: number;
Bene_Ndual_Cnt: number;
Bene_Avg_Risk_Scre: number;
}
async function searchMedicare(
dataset_type: string = "geography_and_service",
year?: string,
hcpcs_code?: string,
geo_level?: string,
geo_code?: string,
place_of_service?: string,
size: number = 10,
offset: number = 0,
text_search?: string,
sort?: { field: string; direction: 'asc' | 'desc' },
provider_type?: string
) {
let datasetVersionId: string;
let selectedYear: string;
if (dataset_type === "geography_and_service") {
selectedYear = year || getLatestYear(versionMapGeography);
datasetVersionId = versionMapGeography[selectedYear];
} else if (dataset_type === "provider_and_service") {
selectedYear = year || getLatestYear(versionMapProviderAndService);
datasetVersionId = versionMapProviderAndService[selectedYear];
} else if (dataset_type === "provider") {
selectedYear = year || getLatestYear(versionMapProvider);
datasetVersionId = versionMapProvider[selectedYear];
} else {
throw new Error(`Invalid dataset_type: ${dataset_type}`);
}
if (!datasetVersionId) {
throw new Error(`Invalid year specified: ${selectedYear} for dataset_type: ${dataset_type}`);
}
const query = new URLSearchParams({
size: Math.min(size, 5000).toString(),
offset: offset.toString()
});
// Add filters using the CMS API filter syntax
if (geo_level && geo_code) {
if (dataset_type === "geography_and_service") {
query.append("filter[Rndrng_Prvdr_Geo_Lvl]", geo_level);
query.append("filter[Rndrng_Prvdr_Geo_Cd]", geo_code);
} else {
// For provider_and_service and provider datasets
if (geo_level === "State") {
query.append("filter[Rndrng_Prvdr_State_Abrvtn]", geo_code);
} else if (geo_level === "County") {
query.append("filter[Rndrng_Prvdr_State_FIPS]", geo_code);
} else if (geo_level === "ZIP") {
query.append("filter[Rndrng_Prvdr_Zip5]", geo_code);
}
}
}
if (hcpcs_code && (dataset_type === "geography_and_service" || dataset_type === "provider_and_service")) {
query.append("filter[HCPCS_Cd]", hcpcs_code);
}
if (place_of_service && (dataset_type === "geography_and_service" || dataset_type === "provider_and_service")) {
query.append("filter[Place_Of_Srvc]", place_of_service);
}
if (provider_type && (dataset_type === "provider_and_service" || dataset_type === "provider")) {
query.append("filter[Rndrng_Prvdr_Type]", provider_type);
}
if (text_search) {
// Add text search filter for relevant fields based on dataset type
if (dataset_type === "provider" || dataset_type === "provider_and_service") {
query.append("Rndrng_Prvdr_Last_Org_Name", text_search);
query.append("Rndrng_Prvdr_First_Name", text_search);
}
if (dataset_type === "geography_and_service" || dataset_type === "provider_and_service") {
query.append("HCPCS_Desc", text_search);
}
}
if (sort) {
query.append("sort", `${sort.direction === 'desc' ? '-' : ''}${sort.field}`);
}
const url = `https://data.cms.gov/data-api/v1/dataset/${datasetVersionId}/data?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json() as (MedicareProviderGeographyResponse[] | MedicareProviderIndividualResponse[] | MedicareProviderResponse[]);
return {
total: data.length,
providers: data.map((item) => {
if (dataset_type === "provider") {
const providerItem = item as MedicareProviderResponse;
return {
npi: providerItem.Rndrng_NPI,
provider_name: `${providerItem.Rndrng_Prvdr_Last_Org_Name}, ${providerItem.Rndrng_Prvdr_First_Name}${providerItem.Rndrng_Prvdr_MI ? ` ${providerItem.Rndrng_Prvdr_MI}` : ''}`,
provider_type: providerItem.Rndrng_Prvdr_Type,
provider_address: providerItem.Rndrng_Prvdr_St1,
provider_city: providerItem.Rndrng_Prvdr_City,
provider_state: providerItem.Rndrng_Prvdr_State_Abrvtn,
provider_zip: providerItem.Rndrng_Prvdr_Zip5,
provider_country: providerItem.Rndrng_Prvdr_Cntry,
medicare_participating: providerItem.Rndrng_Prvdr_Mdcr_Prtcptg_Ind,
total_hcpcs_codes: parseInt(providerItem.Tot_HCPCS_Cds),
total_beneficiaries: providerItem.Tot_Benes,
total_services: providerItem.Tot_Srvcs,
total_submitted_charges: providerItem.Tot_Sbmtd_Chrg,
total_medicare_allowed: providerItem.Tot_Mdcr_Alowd_Amt,
total_medicare_payment: providerItem.Tot_Mdcr_Pymt_Amt,
total_medicare_standardized: providerItem.Tot_Mdcr_Stdzd_Amt,
beneficiary_average_age: providerItem.Bene_Avg_Age,
beneficiary_age_lt_65: providerItem.Bene_Age_LT_65_Cnt,
beneficiary_age_65_74: providerItem.Bene_Age_65_74_Cnt,
beneficiary_age_75_84: providerItem.Bene_Age_75_84_Cnt,
beneficiary_age_gt_84: providerItem.Bene_Age_GT_84_Cnt,
beneficiary_female_count: providerItem.Bene_Feml_Cnt,
beneficiary_male_count: providerItem.Bene_Male_Cnt,
beneficiary_race_white: providerItem.Bene_Race_Wht_Cnt,
beneficiary_race_black: providerItem.Bene_Race_Black_Cnt,
beneficiary_race_api: providerItem.Bene_Race_API_Cnt,
beneficiary_race_hispanic: providerItem.Bene_Race_Hspnc_Cnt,
beneficiary_race_native: providerItem.Bene_Race_NatInd_Cnt,
beneficiary_race_other: providerItem.Bene_Race_Othr_Cnt,
beneficiary_dual_count: providerItem.Bene_Dual_Cnt,
beneficiary_non_dual_count: providerItem.Bene_Ndual_Cnt,
beneficiary_average_risk_score: providerItem.Bene_Avg_Risk_Scre
};
}
if (dataset_type === "geography_and_service") {
const geoItem = item as MedicareProviderGeographyResponse;
return {
hcpcs_code: geoItem.HCPCS_Cd,
hcpcs_desc: geoItem.HCPCS_Desc,
hcpcs_drug_ind: geoItem.HCPCS_Drug_Ind,
place_of_service: geoItem.Place_Of_Srvc,
total_beneficiaries: geoItem.Tot_Benes,
total_services: geoItem.Tot_Srvcs,
total_beneficiary_days: geoItem.Tot_Bene_Day_Srvcs,
avg_submitted_charge: geoItem.Avg_Sbmtd_Chrg,
avg_medicare_allowed: geoItem.Avg_Mdcr_Alowd_Amt,
avg_medicare_payment: geoItem.Avg_Mdcr_Pymt_Amt,
avg_medicare_standardized: geoItem.Avg_Mdcr_Stdzd_Amt,
geo_level: geoItem.Rndrng_Prvdr_Geo_Lvl,
geo_code: geoItem.Rndrng_Prvdr_Geo_Cd,
geo_desc: geoItem.Rndrng_Prvdr_Geo_Desc,
total_providers: geoItem.Tot_Rndrng_Prvdrs
};
} else {
const providerItem = item as MedicareProviderIndividualResponse;
return {
hcpcs_code: providerItem.HCPCS_Cd,
hcpcs_desc: providerItem.HCPCS_Desc,
hcpcs_drug_ind: providerItem.HCPCS_Drug_Ind,
place_of_service: providerItem.Place_Of_Srvc,
total_beneficiaries: providerItem.Tot_Benes,
total_services: providerItem.Tot_Srvcs,
total_beneficiary_days: providerItem.Tot_Bene_Day_Srvcs,
avg_submitted_charge: providerItem.Avg_Sbmtd_Chrg,
avg_medicare_allowed: providerItem.Avg_Mdcr_Alowd_Amt,
avg_medicare_payment: providerItem.Avg_Mdcr_Pymt_Amt,
avg_medicare_standardized: providerItem.Avg_Mdcr_Stdzd_Amt,
npi: providerItem.Rndrng_NPI,
provider_name: `${providerItem.Rndrng_Prvdr_Last_Org_Name}, ${providerItem.Rndrng_Prvdr_First_Name}${providerItem.Rndrng_Prvdr_MI ? ` ${providerItem.Rndrng_Prvdr_MI}` : ''}`,
provider_type: providerItem.Rndrng_Prvdr_Type,
provider_address: providerItem.Rndrng_Prvdr_St1,
provider_city: providerItem.Rndrng_Prvdr_City,
provider_state: providerItem.Rndrng_Prvdr_State_Abrvtn,
provider_zip: providerItem.Rndrng_Prvdr_Zip5,
provider_country: providerItem.Rndrng_Prvdr_Cntry,
medicare_participating: providerItem.Rndrng_Prvdr_Mdcr_Prtcptg_Ind
};
}
})
};
}
async function searchPrescribers(
drug_name?: string,
prescriber_npi?: string,
prescriber_type?: string,
state?: string,
size: number = 10,
offset: number = 0,
sort?: { field: string; direction: 'asc' | 'desc' }
): Promise<any> {
const datasetId = '9552739e-3d05-4c1b-8eff-ecabf391e2e5'; // Medicare Part D Prescribers - by Provider and Drug
const query = new URLSearchParams();
query.append('size', String(size));
query.append('offset', String(offset));
// Use keyword search for drug name (searches across all fields, supports partial match)
if (drug_name) {
query.append('keyword', drug_name);
}
if (prescriber_npi) {
query.append('filter[Prscrbr_NPI]', prescriber_npi);
}
if (prescriber_type) {
query.append('filter[Prscrbr_Type]', prescriber_type);
}
if (state) {
query.append('filter[Prscrbr_State_Abrvtn]', state);
}
if (sort) {
query.append('sort', `${sort.direction === 'desc' ? '-' : ''}${sort.field}`);
}
const url = `https://data.cms.gov/data-api/v1/dataset/${datasetId}/data?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const data = await response.json() as any[];
return {
total: data.length,
prescribers: data.map((item: any) => ({
npi: item.Prscrbr_NPI,
prescriber_name: `${item.Prscrbr_Last_Org_Name}, ${item.Prscrbr_First_Name || ''}`,
prescriber_type: item.Prscrbr_Type,
city: item.Prscrbr_City,
state: item.Prscrbr_State_Abrvtn,
brand_name: item.Brnd_Name,
generic_name: item.Gnrc_Name,
total_claims: item.Tot_Clms,
total_30day_fills: item.Tot_30day_Fills,
total_drug_cost: item.Tot_Drug_Cst,
total_beneficiaries: item.Tot_Benes
}))
};
}
async function searchHospitals(
hospital_name?: string,
hospital_id?: string,
state?: string,
city?: string,
drg_code?: string,
size: number = 10,
offset: number = 0,
sort?: { field: string; direction: 'asc' | 'desc' }
): Promise<any> {
const datasetId = 'ee6fb1a5-39b9-46b3-a980-a7284551a732'; // Medicare Inpatient Hospitals - by Provider
const query = new URLSearchParams();
query.append('size', String(size));
query.append('offset', String(offset));
// Add filters
if (hospital_name) {
query.append('filter[Rndrng_Prvdr_Org_Name]', hospital_name);
}
if (hospital_id) {
query.append('filter[Rndrng_Prvdr_CCN]', hospital_id);
}
if (state) {
query.append('filter[Rndrng_Prvdr_State_Abrvtn]', state);
}
if (city) {
query.append('filter[Rndrng_Prvdr_City]', city);
}
if (drg_code) {
query.append('filter[DRG_Cd]', drg_code);
}
// Add sorting
if (sort) {
query.append('sort', `${sort.direction === 'desc' ? '-' : ''}${sort.field}`);
}
const url = `https://data.cms.gov/data-api/v1/dataset/${datasetId}/data?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const data = await response.json() as any[];
return {
total: data.length,
hospitals: data.map((item: any) => ({
ccn: item.Rndrng_Prvdr_CCN,
hospital_name: item.Rndrng_Prvdr_Org_Name,
street_address: item.Rndrng_Prvdr_St,
city: item.Rndrng_Prvdr_City,
state: item.Rndrng_Prvdr_State_Abrvtn,
zip: item.Rndrng_Prvdr_Zip5,
total_discharges: item.Tot_Dschrgs,
total_beneficiaries: item.Tot_Benes,
total_covered_charges: item.Tot_Submtd_Cvrd_Chrg,
total_medicare_payments: item.Tot_Mdcr_Pymt_Amt,
total_payment_amount: item.Tot_Pymt_Amt,
average_beneficiary_age: item.Bene_Avg_Age,
average_risk_score: item.Bene_Avg_Risk_Scre
}))
};
}
async function searchSpending(
spending_drug_name?: string,
spending_type: string = 'part_d',
year?: string,
size: number = 10,
offset: number = 0,
sort?: { field: string; direction: 'asc' | 'desc' }
): Promise<any> {
const datasetMap: Record<string, string> = {
'part_d': '7e0b4365-fd63-4a29-8f5e-e0ac9f66a81b', // Medicare Part D Spending by Drug
'part_b': '76a714ad-3a2c-43ac-b76d-9dadf8f7d890' // Medicare Part B Spending by Drug
};
const datasetId = datasetMap[spending_type] || datasetMap['part_d'];
const query = new URLSearchParams();
query.append('size', String(size));
query.append('offset', String(offset));
// Add filters
if (spending_drug_name) {
query.append('filter[Brnd_Name]', spending_drug_name);
}
// Add sorting (default to most recent year spending)
if (sort) {
query.append('sort', `${sort.direction === 'desc' ? '-' : ''}${sort.field}`);
} else {
// Default sort by 2023 spending descending
query.append('sort', '-Tot_Spndng_2023');
}
const url = `https://data.cms.gov/data-api/v1/dataset/${datasetId}/data?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const data = await response.json() as any[];
// Transform the wide-format data into long-format with year breakdowns
const drugs = data.map((item: any) => {
const drugInfo: any = {
brand_name: item.Brnd_Name,
generic_name: item.Gnrc_Name,
manufacturer: item.Mftr_Name,
spending_by_year: {} as any
};
// Extract all available years from the data (2019-2023 for Part D)
const years = ['2019', '2020', '2021', '2022', '2023'];
years.forEach(yr => {
if (item[`Tot_Spndng_${yr}`]) {
drugInfo.spending_by_year[yr] = {
total_spending: item[`Tot_Spndng_${yr}`],
total_claims: item[`Tot_Clms_${yr}`],
total_beneficiaries: item[`Tot_Benes_${yr}`],
total_dosage_units: item[`Tot_Dsg_Unts_${yr}`],
avg_spending_per_claim: item[`Avg_Spnd_Per_Clm_${yr}`],
avg_spending_per_beneficiary: item[`Avg_Spnd_Per_Bene_${yr}`],
avg_spending_per_dosage_unit: item[`Avg_Spnd_Per_Dsg_Unt_Wghtd_${yr}`]
};
}
});
// If year filter specified, return only that year's data
if (year && drugInfo.spending_by_year[year]) {
return {
brand_name: drugInfo.brand_name,
generic_name: drugInfo.generic_name,
manufacturer: drugInfo.manufacturer,
year: year,
...drugInfo.spending_by_year[year]
};
}
return drugInfo;
});
return {
total: data.length,
spending_type: spending_type,
year_filter: year || 'all',
drugs: drugs
};
}
/**
* Search Medicare Part D Formulary data from local files
* Uses RxNorm API to lookup RXCUI from drug names, then searches formulary
*/
async function searchFormulary(
drug_name?: string,
ndc_code?: string,
tier?: number,
requires_prior_auth?: boolean,
has_quantity_limit?: boolean,
has_step_therapy?: boolean,
plan_state?: string,
plan_id?: string,
size: number = 25,
offset: number = 0
): Promise<any> {
// Support both .txt and .txt.gz files
const formularyBasePath = path.join(__dirname, '..', 'data', 'formulary', 'formulary.txt');
const plansBasePath = path.join(__dirname, '..', 'data', 'formulary', 'plans.txt');
const formularyPath = fs.existsSync(formularyBasePath + '.gz') ? formularyBasePath + '.gz' : formularyBasePath;
const plansPath = fs.existsSync(plansBasePath + '.gz') ? plansBasePath + '.gz' : plansBasePath;
if (!fs.existsSync(formularyPath)) {
throw new Error(`Formulary data file not found at ${formularyPath}`);
}
// If drug name provided, lookup RXCUI codes from RxNorm API
let targetRxcuis: string[] = [];
if (drug_name) {
try {
const rxnormUrl = `https://rxnav.nlm.nih.gov/REST/drugs.json?name=${encodeURIComponent(drug_name)}`;
const rxnormResponse = await fetch(rxnormUrl);
const rxnormData = await rxnormResponse.json() as any;
if (rxnormData.drugGroup?.conceptGroup) {
for (const group of rxnormData.drugGroup.conceptGroup) {
if (group.conceptProperties) {
targetRxcuis = group.conceptProperties.map((prop: any) => prop.rxcui);
break;
}
}
}
if (targetRxcuis.length === 0) {
return {
total: 0,
offset: offset,
limit: size,
drug_name_searched: drug_name,
rxcuis_found: [],
message: `No RXCUI codes found for drug name: ${drug_name}`,
formulary_entries: []
};
}
} catch (error) {
throw new Error(`RxNorm API error: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Load plan info for state filtering and plan name lookups
const planMap = new Map<string, any>();
const validFormularyIds = new Set<string>();
if (fs.existsSync(plansPath)) {
// Handle both .txt and .txt.gz files
const planFileStream = fs.createReadStream(plansPath);
const planStream = plansPath.endsWith('.gz') ? planFileStream.pipe(zlib.createGunzip()) : planFileStream;
const planRL = readline.createInterface({ input: planStream, crlfDelay: Infinity });
let isFirstLine = true;
for await (const line of planRL) {
if (isFirstLine) {
isFirstLine = false;
continue;
}
const values = line.split('|');
const formularyId = values[5]; // FORMULARY_ID
const state = values[10]; // STATE
// Apply state filter if specified
if (plan_state && state !== plan_state) {
continue;
}
validFormularyIds.add(formularyId);
if (!planMap.has(formularyId)) {
planMap.set(formularyId, {
contract_id: values[0],
plan_id: values[1],
plan_name: values[4],
formulary_id: formularyId,
state: state
});
}
}
}
// Stream through formulary file and apply filters
// Handle both .txt and .txt.gz files
const formularyFileStream = fs.createReadStream(formularyPath);
const formularyStream = formularyPath.endsWith('.gz') ? formularyFileStream.pipe(zlib.createGunzip()) : formularyFileStream;
const rl = readline.createInterface({ input: formularyStream, crlfDelay: Infinity });
const results: any[] = [];
let matchCount = 0;
let lineNum = 0;
for await (const line of rl) {
lineNum++;
if (lineNum === 1) continue; // Skip header
const values = line.split('|');
const formularyId = values[0];
const rxcui = values[3];
const ndc = values[4];
const tierValue = values[5];
const quantityLimitYN = values[6];
const priorAuthYN = values[9];
const stepTherapyYN = values[10];
// Apply filters
let matches = true;
// Filter by formulary ID (from plan/state filter)
if (plan_state && !validFormularyIds.has(formularyId)) {
matches = false;
}
// Filter by plan ID
if (plan_id && formularyId !== plan_id) {
matches = false;
}
// Filter by RXCUI (from drug name lookup)
if (drug_name && targetRxcuis.length > 0 && !targetRxcuis.includes(rxcui)) {
matches = false;
}
// Filter by NDC
if (ndc_code && ndc !== ndc_code) {
matches = false;
}
// Filter by tier
if (tier !== undefined && tierValue !== String(tier)) {
matches = false;
}
// Filter by prior authorization
if (requires_prior_auth !== undefined) {
const hasPriorAuth = priorAuthYN === 'Y';
if (requires_prior_auth !== hasPriorAuth) {
matches = false;
}
}
// Filter by quantity limit
if (has_quantity_limit !== undefined) {
const hasQL = quantityLimitYN === 'Y';
if (has_quantity_limit !== hasQL) {
matches = false;
}
}
// Filter by step therapy
if (has_step_therapy !== undefined) {
const hasST = stepTherapyYN === 'Y';
if (has_step_therapy !== hasST) {
matches = false;
}
}
if (matches) {
matchCount++;
// Apply pagination
if (matchCount > offset && results.length < size) {
const planInfo = planMap.get(formularyId);
results.push({
formulary_id: formularyId,
plan_name: planInfo?.plan_name || 'Unknown',
state: planInfo?.state || 'Unknown',
rxcui: rxcui,
ndc: ndc,
tier_level: parseInt(tierValue),
quantity_limit: quantityLimitYN === 'Y',
quantity_limit_amount: values[7],
quantity_limit_days: values[8],
prior_authorization: priorAuthYN === 'Y',
step_therapy: stepTherapyYN === 'Y'
});
}
// Stop if we have enough results
if (results.length >= size) {
break;
}
}
}
return {
total: matchCount,
offset: offset,
limit: size,
drug_name_searched: drug_name,
rxcuis_found: targetRxcuis,
formulary_entries: results
};
}
/**
* Get hospital star ratings from CMS Hospital General Information dataset
*/
async function getHospitalStarRating(
hospital_id?: string,
state?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = 'xubh-q36u'; // Hospital General Information
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
hospitals: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
address: item.address,
city: item.citytown,
state: item.state,
zip_code: item.zip_code,
hospital_overall_rating: item.hospital_overall_rating,
hospital_type: item.hospital_type,
hospital_ownership: item.hospital_ownership,
emergency_services: item.emergency_services === 'Yes',
mortality_measures_count: item.mort_group_measure_count,
safety_measures_count: item.safety_group_measure_count,
readmission_measures_count: item.readm_group_measure_count,
patient_experience_measures_count: item.pt_exp_group_measure_count
}))
};
}
/**
* Get hospital readmission rates from CMS Unplanned Hospital Visits dataset
*/
async function getReadmissionRates(
hospital_id?: string,
state?: string,
condition?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = '632h-zaca'; // Unplanned Hospital Visits - Hospital
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
// Map condition names to measure IDs
if (condition) {
const conditionMap: { [key: string]: string } = {
'heart_attack': 'READM_30_AMI',
'heart_failure': 'READM_30_HF',
'pneumonia': 'READM_30_PN',
'copd': 'READM_30_COPD',
'cabg': 'READM_30_CABG',
'hip_knee': 'READM_30_HIP_KNEE'
};
const measureId = conditionMap[condition.toLowerCase()];
if (measureId) {
query.append(`conditions[${conditionIndex}][property]`, 'measure_id');
query.append(`conditions[${conditionIndex}][value]`, measureId);
conditionIndex++;
}
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
readmissions: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
state: item.state,
measure_id: item.measure_id,
measure_name: item.measure_name,
compared_to_national: item.compared_to_national,
score: item.score,
denominator: item.denominator,
lower_estimate: item.lower_estimate,
higher_estimate: item.higher_estimate,
number_of_patients: item.number_of_patients,
number_of_patients_returned: item.number_of_patients_returned,
start_date: item.start_date,
end_date: item.end_date
}))
};
}
/**
* Get hospital-acquired infections (HAI) data
*/
async function getHospitalInfections(
hospital_id?: string,
state?: string,
infection_type?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = '77hc-ibv8'; // Healthcare Associated Infections - Hospital
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
// Map infection type to measure ID
if (infection_type) {
const infectionMap: { [key: string]: string } = {
'CLABSI': 'HAI_1_SIR',
'CAUTI': 'HAI_2_SIR',
'SSI': 'HAI_3_SIR',
'CDIFF': 'HAI_6_SIR',
'MRSA': 'HAI_5_SIR'
};
const measureId = infectionMap[infection_type.toUpperCase()];
if (measureId) {
query.append(`conditions[${conditionIndex}][property]`, 'measure_id');
query.append(`conditions[${conditionIndex}][value]`, measureId);
conditionIndex++;
}
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
infections: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
state: item.state,
measure_id: item.measure_id,
measure_name: item.measure_name,
compared_to_national: item.compared_to_national,
score: item.score, // SIR - Standardized Infection Ratio
start_date: item.start_date,
end_date: item.end_date
}))
};
}
/**
* Get hospital mortality rates
*/
async function getMortalityRates(
hospital_id?: string,
state?: string,
condition?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = 'ynj2-r877'; // Complications and Deaths - Hospital
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
// Map condition names to measure IDs
if (condition) {
const conditionMap: { [key: string]: string } = {
'heart_attack': 'MORT_30_AMI',
'heart_failure': 'MORT_30_HF',
'pneumonia': 'MORT_30_PN',
'cabg': 'MORT_30_CABG',
'copd': 'MORT_30_COPD',
'stroke': 'MORT_30_STK'
};
const measureId = conditionMap[condition.toLowerCase()];
if (measureId) {
query.append(`conditions[${conditionIndex}][property]`, 'measure_id');
query.append(`conditions[${conditionIndex}][value]`, measureId);
conditionIndex++;
}
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
mortality: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
state: item.state,
measure_id: item.measure_id,
measure_name: item.measure_name,
compared_to_national: item.compared_to_national,
score: item.score,
denominator: item.denominator,
lower_estimate: item.lower_estimate,
higher_estimate: item.higher_estimate,
start_date: item.start_date,
end_date: item.end_date
}))
};
}
/**
* Search hospitals by quality metrics
*/
async function searchHospitalsByQuality(
state?: string,
min_star_rating?: number,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = 'xubh-q36u'; // Hospital General Information
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
let data = Array.isArray(responseData) ? responseData : (responseData.results || []);
// Filter by min_star_rating if provided (client-side filter since API doesn't support >= operations)
if (min_star_rating) {
data = data.filter((item: any) => {
const rating = parseInt(item.hospital_overall_rating);
return !isNaN(rating) && rating >= min_star_rating;
});
}
return {
total: data.length,
hospitals: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
address: item.address,
city: item.citytown,
state: item.state,
zip_code: item.zip_code,
hospital_overall_rating: item.hospital_overall_rating,
hospital_type: item.hospital_type,
hospital_ownership: item.hospital_ownership,
emergency_services: item.emergency_services === 'Yes'
}))
};
}
/**
* Compare hospitals across multiple quality metrics
*/
async function compareHospitals(
hospital_ids: string[],
metrics?: string[],
size: number = 100
): Promise<any> {
if (!hospital_ids || hospital_ids.length === 0) {
throw new Error('hospital_ids array is required');
}
const results: any = {
hospitals: []
};
// Fetch data for each hospital
for (const hospitalId of hospital_ids) {
const hospitalData: any = {
facility_id: hospitalId
};
// Get star rating if requested
if (!metrics || metrics.includes('star_rating')) {
const starData = await getHospitalStarRating(hospitalId, undefined, 1, 0);
if (starData.hospitals.length > 0) {
hospitalData.facility_name = starData.hospitals[0].facility_name;
hospitalData.star_rating = starData.hospitals[0].hospital_overall_rating;
}
}
// Get readmission rates if requested
if (!metrics || metrics.includes('readmission_rate')) {
const readmissionData = await getReadmissionRates(hospitalId, undefined, undefined, 10, 0);
hospitalData.readmissions = readmissionData.readmissions;
}
// Get mortality rates if requested
if (!metrics || metrics.includes('mortality_rate')) {
const mortalityData = await getMortalityRates(hospitalId, undefined, undefined, 10, 0);
hospitalData.mortality = mortalityData.mortality;
}
// Get infection rates if requested
if (!metrics || metrics.includes('infection_rate')) {
const infectionData = await getHospitalInfections(hospitalId, undefined, undefined, 10, 0);
hospitalData.infections = infectionData.infections;
}
results.hospitals.push(hospitalData);
}
return results;
}
/**
* Get Hospital Value-Based Purchasing (VBP) performance scores
*/
async function getVbpScores(
hospital_id?: string,
state?: string,
domain?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = 'ypbt-wvdk'; // Hospital Value-Based Purchasing - Total Performance Score
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
vbp_scores: data.map((item: any) => {
const result: any = {
facility_id: item.facility_id,
facility_name: item.facility_name,
state: item.state,
fiscal_year: item.fiscal_year,
total_performance_score: item.total_performance_score
};
// Add domain-specific scores based on filter
if (!domain || domain === 'all' || domain === 'clinical_outcomes') {
result.clinical_outcomes_score = item.weighted_normalized_clinical_outcomes_domain_score;
}
if (!domain || domain === 'all' || domain === 'person_community_engagement') {
result.person_community_engagement_score = item.weighted_person_and_community_engagement_domain_score;
}
if (!domain || domain === 'all' || domain === 'safety') {
result.safety_score = item.weighted_safety_domain_score;
}
if (!domain || domain === 'all' || domain === 'efficiency_cost_reduction') {
result.efficiency_cost_reduction_score = item.weighted_efficiency_and_cost_reduction_domain_score;
}
return result;
})
};
}
/**
* Get Hospital Consumer Assessment of Healthcare Providers and Systems (HCAHPS) patient experience scores
*/
async function getHcahpsScores(
hospital_id?: string,
state?: string,
measure?: string,
size: number = 10,
offset: number = 0
): Promise<any> {
const datasetId = 'dgck-syfz'; // Patient survey (HCAHPS) - Hospital
const query = new URLSearchParams();
query.append('limit', String(size));
query.append('offset', String(offset));
let conditionIndex = 0;
if (hospital_id) {
query.append(`conditions[${conditionIndex}][property]`, 'facility_id');
query.append(`conditions[${conditionIndex}][value]`, hospital_id);
conditionIndex++;
}
if (state) {
query.append(`conditions[${conditionIndex}][property]`, 'state');
query.append(`conditions[${conditionIndex}][value]`, state);
conditionIndex++;
}
if (measure) {
query.append(`conditions[${conditionIndex}][property]`, 'hcahps_measure_id');
query.append(`conditions[${conditionIndex}][value]`, measure);
conditionIndex++;
}
const url = `https://data.cms.gov/provider-data/api/1/datastore/query/${datasetId}/0?${query.toString()}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`CMS API error: ${response.statusText}`);
}
const responseData = await response.json() as any;
const data = Array.isArray(responseData) ? responseData : (responseData.results || []);
return {
total: data.length,
hcahps_scores: data.map((item: any) => ({
facility_id: item.facility_id,
facility_name: item.facility_name,
state: item.state,
measure_id: item.hcahps_measure_id,
measure_question: item.hcahps_question,
answer_description: item.hcahps_answer_description,
answer_percent: item.hcahps_answer_percent,
star_rating: item.patient_survey_star_rating,
linear_mean_value: item.hcahps_linear_mean_value,
number_of_surveys: item.number_of_completed_surveys,
response_rate_percent: item.survey_response_rate_percent,
start_date: item.start_date,
end_date: item.end_date
}))
};
}
/**
* Helper: Get current quarter in format YYYYQN
*/
function getCurrentQuarter(): string {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const quarter = Math.ceil(month / 3);
return `${year}Q${quarter}`;
}
/**
* Helper: Parse quarter string to get file path
*/
function getAspFilePath(quarter: string): string {
const aspBasePath = path.join(__dirname, '..', 'data', 'asp', `${quarter}_ASP_Pricing.csv`);
const gzPath = aspBasePath + '.gz';
if (fs.existsSync(gzPath)) {
return gzPath;
}
if (fs.existsSync(aspBasePath)) {
return aspBasePath;
}
throw new Error(`ASP data file not found for quarter ${quarter}. Expected at: ${aspBasePath} or ${gzPath}`);
}
/**
* Helper: Load ASP data for a specific quarter
*/
async function loadAspData(quarter: string): Promise<Map<string, any>> {
const filePath = getAspFilePath(quarter);
const aspData = new Map<string, any>();
const fileStream = fs.createReadStream(filePath);
const dataStream = filePath.endsWith('.gz') ? fileStream.pipe(zlib.createGunzip()) : fileStream;
const rl = readline.createInterface({ input: dataStream, crlfDelay: Infinity });
let isFirstLine = true;
for await (const line of rl) {
if (isFirstLine) {
isFirstLine = false;
continue; // Skip header
}
const values = line.split(',');
if (values.length < 4) continue;
const hcpcsCode = values[0]?.trim();
const shortDesc = values[1]?.trim().replace(/^"|"$/g, ''); // Remove quotes
const dosage = values[2]?.trim();
const paymentLimit = parseFloat(values[3]?.trim() || '0');
const coinsurancePct = parseFloat(values[4]?.trim() || '20');
const notes = values[10]?.trim().replace(/^"|"$/g, '') || '';
if (hcpcsCode) {
aspData.set(hcpcsCode, {
hcpcs_code: hcpcsCode,
short_descriptor: shortDesc,
dosage: dosage,
payment_limit: paymentLimit,
coinsurance_percentage: coinsurancePct,
asp_calculated: paymentLimit / 1.06, // Reverse calculate ASP from payment limit
quarter: quarter,
notes: notes
});
}
}
return aspData;
}
/**
* Get ASP pricing for Medicare Part B drugs
* Provides current pricing data for physician-administered drugs
*/
async function getAspPricing(
hcpcs_code: string,
quarter?: string
): Promise<any> {
const targetQuarter = quarter || getCurrentQuarter();
if (!hcpcs_code) {
throw new Error('hcpcs_code parameter is required');
}
const aspData = await loadAspData(targetQuarter);
const result = aspData.get(hcpcs_code.toUpperCase());
if (!result) {
return {
hcpcs_code: hcpcs_code.toUpperCase(),
quarter: targetQuarter,
found: false,
message: `HCPCS code ${hcpcs_code} not found in ${targetQuarter} ASP data. This code may not be a Part B drug or may not have ASP pricing.`
};
}
return {
found: true,
...result,
medicare_reimbursement: result.payment_limit,
patient_coinsurance: (result.payment_limit * result.coinsurance_percentage / 100).toFixed(2),
effective_period: `${targetQuarter} (${getQuarterDates(targetQuarter)})`,
data_source: 'CMS Medicare Part B ASP Pricing File'
};
}
/**
* Helper: Get quarter date range
*/
function getQuarterDates(quarter: string): string {
const [year, q] = quarter.split('Q');
const quarters = {
'1': `Jan 1 - Mar 31, ${year}`,
'2': `Apr 1 - Jun 30, ${year}`,
'3': `Jul 1 - Sep 30, ${year}`,
'4': `Oct 1 - Dec 31, ${year}`
};
return quarters[q as keyof typeof quarters] || '';
}
/**
* Get ASP pricing trends over time
* Tracks how drug pricing changes across multiple quarters
*/
async function getAspTrend(
hcpcs_code: string,
start_quarter: string,
end_quarter: string
): Promise<any> {
if (!hcpcs_code) {
throw new Error('hcpcs_code parameter is required');
}
if (!start_quarter || !end_quarter) {
throw new Error('start_quarter and end_quarter parameters are required');
}
const code = hcpcs_code.toUpperCase();
const trend: any[] = [];
const quarters = generateQuarterRange(start_quarter, end_quarter);
for (const quarter of quarters) {
try {
const aspData = await loadAspData(quarter);
const result = aspData.get(code);
if (result) {
trend.push({
quarter: quarter,
payment_limit: result.payment_limit,
asp_calculated: result.asp_calculated,
dosage: result.dosage,
dates: getQuarterDates(quarter)
});
}
} catch (error) {
// Quarter data not available, skip
logger.warn(`ASP data not available for quarter ${quarter}`);
}
}
if (trend.length === 0) {
return {
hcpcs_code: code,
start_quarter,
end_quarter,
found: false,
message: `No ASP data found for ${code} in the specified quarter range`
};
}
// Calculate trend statistics
const prices = trend.map(t => t.payment_limit);
const minPrice = Math.min(...prices);
const maxPrice = Math.max(...prices);
const avgPrice = prices.reduce((a, b) => a + b, 0) / prices.length;
const priceChange = ((prices[prices.length - 1] - prices[0]) / prices[0] * 100).toFixed(2);
return {
hcpcs_code: code,
drug_name: trend[0].short_descriptor || 'Unknown',
start_quarter,
end_quarter,
data_points: trend.length,
trend_data: trend,
analysis: {
min_price: minPrice.toFixed(2),
max_price: maxPrice.toFixed(2),
avg_price: avgPrice.toFixed(2),
price_change_percent: priceChange,
price_volatility: ((maxPrice - minPrice) / avgPrice * 100).toFixed(2) + '%'
}
};
}
/**
* Helper: Generate array of quarters between start and end
*/
function generateQuarterRange(start: string, end: string): string[] {
const quarters: string[] = [];
const [startYear, startQ] = start.split('Q').map(Number);
const [endYear, endQ] = end.split('Q').map(Number);
for (let year = startYear; year <= endYear; year++) {
const firstQ = (year === startYear) ? startQ : 1;
const lastQ = (year === endYear) ? endQ : 4;
for (let q = firstQ; q <= lastQ; q++) {
quarters.push(`${year}Q${q}`);
}
}
return quarters;
}
/**
* Compare ASP pricing across multiple drugs
* Useful for competitive pricing analysis
*/
async function compareAspPricing(
hcpcs_codes: string[],
quarter?: string
): Promise<any> {
if (!hcpcs_codes || hcpcs_codes.length === 0) {
throw new Error('hcpcs_codes parameter is required and must be a non-empty array');
}
const targetQuarter = quarter || getCurrentQuarter();
const aspData = await loadAspData(targetQuarter);
const comparisons: any[] = [];
for (const code of hcpcs_codes) {
const result = aspData.get(code.toUpperCase());
if (result) {
comparisons.push({
hcpcs_code: result.hcpcs_code,
drug_name: result.short_descriptor,
dosage: result.dosage,
payment_limit: result.payment_limit,
asp_calculated: result.asp_calculated,
patient_coinsurance: (result.payment_limit * result.coinsurance_percentage / 100).toFixed(2),
notes: result.notes
});
} else {
comparisons.push({
hcpcs_code: code.toUpperCase(),
found: false,
message: 'Not found in ASP data'
});
}
}
// Calculate comparison stats
const found = comparisons.filter(c => c.found !== false);
const prices = found.map(c => c.payment_limit);
return {
quarter: targetQuarter,
effective_period: getQuarterDates(targetQuarter),
drugs_compared: hcpcs_codes.length,
drugs_found: found.length,
comparisons: comparisons,
analysis: found.length > 0 ? {
lowest_price: Math.min(...prices).toFixed(2),
highest_price: Math.max(...prices).toFixed(2),
average_price: (prices.reduce((a, b) => a + b, 0) / prices.length).toFixed(2),
price_range: (Math.max(...prices) - Math.min(...prices)).toFixed(2)
} : null
};
}
/**
* Helper: Generate array of months between start and end
*/
function generateMonthRange(start: string, end: string): string[] {
const months: string[] = [];
const startYear = parseInt(start.substring(0, 4));
const startMonth = parseInt(start.substring(4, 6));
const endYear = parseInt(end.substring(0, 4));
const endMonth = parseInt(end.substring(4, 6));
for (let year = startYear; year <= endYear; year++) {
const firstMonth = (year === startYear) ? startMonth : 1;
const lastMonth = (year === endYear) ? endMonth : 12;
for (let month = firstMonth; month <= lastMonth; month++) {
months.push(`${year}${month.toString().padStart(2, '0')}`);
}
}
return months;
}
/**
* Helper: Load formulary data for a specific month
*/
async function loadFormularyMonth(month: string, drug_name?: string, rxcui?: string): Promise<Map<string, any>> {
const formularyBasePath = path.join(__dirname, '..', 'data', 'formulary', `${month}_formulary.txt`);
const gzPath = formularyBasePath + '.gz';
let filePath: string;
if (fs.existsSync(gzPath)) {
filePath = gzPath;
} else if (fs.existsSync(formularyBasePath)) {
filePath = formularyBasePath;
} else {
throw new Error(`Formulary data not found for month ${month}`);
}
// If drug_name provided, lookup RXCUI first
let targetRxcuis: string[] = rxcui ? [rxcui] : [];
if (drug_name && !rxcui) {
try {
const rxnormUrl = `https://rxnav.nlm.nih.gov/REST/drugs.json?name=${encodeURIComponent(drug_name)}`;
const rxnormResponse = await fetch(rxnormUrl);
const rxnormData = await rxnormResponse.json() as any;
if (rxnormData.drugGroup?.conceptGroup) {
for (const group of rxnormData.drugGroup.conceptGroup) {
if (group.conceptProperties) {
targetRxcuis = group.conceptProperties.map((prop: any) => prop.rxcui);
break;
}
}
}
} catch (error) {
logger.warn(`RxNorm lookup failed for ${drug_name}: ${error instanceof Error ? error.message : String(error)}`);
}
}
if (targetRxcuis.length === 0 && !rxcui) {
throw new Error(`No RXCUI found for drug: ${drug_name}`);
}
// Aggregate formulary data by plan
const fileStream = fs.createReadStream(filePath);
const dataStream = filePath.endsWith('.gz') ? fileStream.pipe(zlib.createGunzip()) : fileStream;
const rl = readline.createInterface({ input: dataStream, crlfDelay: Infinity });
const stats = {
total_plans: new Set<string>(),
plans_with_coverage: new Set<string>(),
prior_auth_plans: new Set<string>(),
quantity_limit_plans: new Set<string>(),
tiers: [] as number[]
};
let lineNum = 0;
for await (const line of rl) {
lineNum++;
if (lineNum === 1) continue; // Skip header
const values = line.split('|');
const formularyId = values[0];
const lineRxcui = values[3];
const tierValue = parseInt(values[5] || '0');
const quantityLimitYN = values[6];
const priorAuthYN = values[9];
// Filter by RXCUI
if (targetRxcuis.length > 0 && !targetRxcuis.includes(lineRxcui)) {
continue;
}
stats.total_plans.add(formularyId);
stats.plans_with_coverage.add(formularyId);
if (priorAuthYN === 'Y') {
stats.prior_auth_plans.add(formularyId);
}
if (quantityLimitYN === 'Y') {
stats.quantity_limit_plans.add(formularyId);
}
if (tierValue > 0) {
stats.tiers.push(tierValue);
}
}
const result = new Map<string, any>();
result.set('stats', {
total_plans: stats.total_plans.size,
plans_with_coverage: stats.plans_with_coverage.size,
coverage_rate: stats.plans_with_coverage.size / (stats.total_plans.size || 1),
prior_auth_rate: stats.prior_auth_plans.size / (stats.plans_with_coverage.size || 1),
quantity_limit_rate: stats.quantity_limit_plans.size / (stats.plans_with_coverage.size || 1),
avg_tier: stats.tiers.length > 0 ? stats.tiers.reduce((a, b) => a + b, 0) / stats.tiers.length : 0
});
return result;
}
/**
* Get formulary trend analysis over time
* Tracks how formulary policies change across multiple months
*/
async function getFormularyTrend(
start_month: string,
end_month: string,
drug_name?: string,
rxcui?: string,
trend_metric?: string
): Promise<any> {
const metric = trend_metric || 'all';
if (!drug_name && !rxcui) {
throw new Error('Either drug_name or rxcui parameter is required');
}
if (!start_month || !end_month) {
throw new Error('start_month and end_month parameters are required');
}
const months = generateMonthRange(start_month, end_month);
const trendData: any[] = [];
for (const month of months) {
try {
const data = await loadFormularyMonth(month, drug_name, rxcui);
const stats = data.get('stats');
if (stats) {
trendData.push({
month: month,
month_label: `${month.substring(0, 4)}-${month.substring(4, 6)}`,
...stats
});
}
} catch (error) {
// Month data not available, skip
logger.warn(`Formulary data not available for month ${month}`);
}
}
if (trendData.length === 0) {
return {
drug_name: drug_name || rxcui,
start_month,
end_month,
found: false,
message: `No formulary data found for the specified month range`
};
}
// Calculate trend analysis
const first = trendData[0];
const last = trendData[trendData.length - 1];
return {
drug_name: drug_name || rxcui,
rxcui: rxcui,
start_month,
end_month,
data_points: trendData.length,
trend_data: trendData,
analysis: {
coverage_change: ((last.coverage_rate - first.coverage_rate) * 100).toFixed(2) + '%',
prior_auth_change: ((last.prior_auth_rate - first.prior_auth_rate) * 100).toFixed(2) + '%',
quantity_limit_change: ((last.quantity_limit_rate - first.quantity_limit_rate) * 100).toFixed(2) + '%',
avg_tier_change: (last.avg_tier - first.avg_tier).toFixed(2),
overall_assessment: assessFormularyTrend(first, last)
}
};
}
/**
* Helper: Assess overall formulary trend
*/
function assessFormularyTrend(first: any, last: any): string {
const priorAuthIncrease = last.prior_auth_rate - first.prior_auth_rate;
const tierIncrease = last.avg_tier - first.avg_tier;
const coverageDecrease = first.coverage_rate - last.coverage_rate;
if (priorAuthIncrease > 0.1 || tierIncrease > 0.5 || coverageDecrease > 0.05) {
return "Access deteriorating - increased restrictions";
} else if (priorAuthIncrease < -0.05 || tierIncrease < -0.3) {
return "Access improving - reduced restrictions";
} else {
return "Access stable - minimal changes";
}
}
function sendError(res: http.ServerResponse, message: string, code: number = 400) {
res.writeHead(code, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: message, code }));
}
async function runServer() {
if (!USE_HTTP) {
// MCP mode (stdio only)
const { Server } = await import('@modelcontextprotocol/sdk/server/index.js');
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
const { CallToolRequestSchema, ListToolsRequestSchema, McpError } = await import('@modelcontextprotocol/sdk/types.js');
// Initialize server without any console output
const transport = new StdioServerTransport();
const server = new Server(
{ name: "mcp-healthcare-data", version: "0.2.14" },
{ capabilities: { tools: {} } }
);
// Set up request handlers
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: MEDICARE_INFO_TOOL.name,
description: MEDICARE_INFO_TOOL.description,
inputSchema: MEDICARE_INFO_TOOL.input_schema
}
]
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const toolName = request.params?.name;
const args = request.params?.arguments;
try {
switch (toolName) {
case 'medicare_info': {
const method = (args as any)?.method;
switch (method) {
case 'search_providers': {
const result = await searchMedicare(
(args as any)?.dataset_type,
(args as any)?.year,
(args as any)?.hcpcs_code,
(args as any)?.geo_level,
(args as any)?.geo_code,
(args as any)?.place_of_service,
(args as any)?.size,
(args as any)?.offset,
(args as any)?.text_search,
(args as any)?.sort,
(args as any)?.provider_type
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'search_prescribers': {
const result = await searchPrescribers(
(args as any)?.drug_name,
(args as any)?.prescriber_npi,
(args as any)?.prescriber_type,
(args as any)?.state,
(args as any)?.size,
(args as any)?.offset,
(args as any)?.sort
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'search_hospitals': {
const result = await searchHospitals(
(args as any)?.hospital_name,
(args as any)?.hospital_id,
(args as any)?.state,
(args as any)?.city,
(args as any)?.drg_code,
(args as any)?.size,
(args as any)?.offset,
(args as any)?.sort
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'search_spending': {
const result = await searchSpending(
(args as any)?.spending_drug_name,
(args as any)?.spending_type,
(args as any)?.year,
(args as any)?.size,
(args as any)?.offset,
(args as any)?.sort
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'search_formulary': {
const result = await searchFormulary(
(args as any)?.formulary_drug_name,
(args as any)?.ndc_code,
(args as any)?.tier,
(args as any)?.requires_prior_auth,
(args as any)?.has_quantity_limit,
(args as any)?.has_step_therapy,
(args as any)?.plan_state,
(args as any)?.plan_id,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_hospital_star_rating': {
const result = await getHospitalStarRating(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_readmission_rates': {
const result = await getReadmissionRates(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.condition,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_hospital_infections': {
const result = await getHospitalInfections(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.infection_type,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_mortality_rates': {
const result = await getMortalityRates(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.condition,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'search_hospitals_by_quality': {
const result = await searchHospitalsByQuality(
(args as any)?.quality_state,
(args as any)?.min_star_rating,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'compare_hospitals': {
const result = await compareHospitals(
(args as any)?.hospital_ids,
(args as any)?.metrics,
(args as any)?.size
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_vbp_scores': {
const result = await getVbpScores(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.vbp_domain,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_hcahps_scores': {
const result = await getHcahpsScores(
(args as any)?.quality_hospital_id,
(args as any)?.quality_state,
(args as any)?.hcahps_measure,
(args as any)?.size,
(args as any)?.offset
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_asp_pricing': {
const result = await getAspPricing(
(args as any)?.hcpcs_code_asp,
(args as any)?.quarter
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_asp_trend': {
const result = await getAspTrend(
(args as any)?.hcpcs_code_asp,
(args as any)?.start_quarter,
(args as any)?.end_quarter
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'compare_asp_pricing': {
const result = await compareAspPricing(
(args as any)?.hcpcs_codes,
(args as any)?.quarter
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
case 'get_formulary_trend': {
const result = await getFormularyTrend(
(args as any)?.start_month,
(args as any)?.end_month,
(args as any)?.drug_name,
(args as any)?.rxcui,
(args as any)?.trend_metric
);
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], isError: false };
}
default:
throw new McpError(-32602, `Unknown method: ${method}. Valid methods: search_providers, search_prescribers, search_hospitals, search_spending, search_formulary, get_hospital_star_rating, get_readmission_rates, get_hospital_infections, get_mortality_rates, search_hospitals_by_quality, compare_hospitals, get_vbp_scores, get_hcahps_scores, get_asp_pricing, get_asp_trend, compare_asp_pricing, get_formulary_trend`);
}
}
default:
throw new McpError(-32603, 'Unknown tool');
}
} catch (error) {
throw new McpError(-32603, error instanceof Error ? error.message : String(error));
}
});
await server.connect(transport);
} else {
const server = http.createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
const method = req.method || '';
const url = req.url || '';
// Health check endpoint
if (method === 'GET' && url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
return;
}
// List tools endpoint
if (method === 'POST' && url === '/list_tools') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
tools: [
{
name: MEDICARE_INFO_TOOL.name,
description: MEDICARE_INFO_TOOL.description,
input_schema: MEDICARE_INFO_TOOL.input_schema,
responseSchema: MEDICARE_INFO_TOOL.responseSchema
}
]
}));
return;
}
// Helper to parse JSON body
const parseBody = (req: http.IncomingMessage) => new Promise<any>((resolve, reject) => {
let body = '';
req.on('data', (chunk: any) => { body += chunk; });
req.on('end', () => {
try { resolve(JSON.parse(body)); } catch (e) { reject(e); }
});
});
// Routing for all tools
if (method === 'POST') {
let data: any;
let result: any;
try {
data = await parseBody(req);
const url = req.url || '';
if (url === '/medicare_info') {
const methodName = data.method;
switch (methodName) {
case 'search_providers':
result = await searchMedicare(data.dataset_type, data.year, data.hcpcs_code, data.geo_level, data.geo_code, data.place_of_service, data.size, data.offset, data.text_search, data.sort, data.provider_type);
break;
case 'search_prescribers':
result = await searchPrescribers(data.drug_name, data.prescriber_npi, data.prescriber_type, data.state, data.size, data.offset, data.sort);
break;
case 'search_hospitals':
result = await searchHospitals(data.hospital_name, data.hospital_id, data.state, data.city, data.drg_code, data.size, data.offset, data.sort);
break;
case 'search_spending':
result = await searchSpending(data.spending_drug_name, data.spending_type, data.year, data.size, data.offset, data.sort);
break;
case 'search_formulary':
result = await searchFormulary(data.formulary_drug_name, data.ndc_code, data.tier, data.requires_prior_auth, data.has_quantity_limit, data.has_step_therapy, data.plan_state, data.plan_id, data.size, data.offset);
break;
case 'get_hospital_star_rating':
result = await getHospitalStarRating(data.quality_hospital_id, data.quality_state, data.size, data.offset);
break;
case 'get_readmission_rates':
result = await getReadmissionRates(data.quality_hospital_id, data.quality_state, data.condition, data.size, data.offset);
break;
case 'get_hospital_infections':
result = await getHospitalInfections(data.quality_hospital_id, data.quality_state, data.infection_type, data.size, data.offset);
break;
case 'get_mortality_rates':
result = await getMortalityRates(data.quality_hospital_id, data.quality_state, data.condition, data.size, data.offset);
break;
case 'search_hospitals_by_quality':
result = await searchHospitalsByQuality(data.quality_state, data.min_star_rating, data.size, data.offset);
break;
case 'compare_hospitals':
result = await compareHospitals(data.hospital_ids, data.metrics, data.size);
break;
case 'get_vbp_scores':
result = await getVbpScores(data.quality_hospital_id, data.quality_state, data.vbp_domain, data.size, data.offset);
break;
case 'get_hcahps_scores':
result = await getHcahpsScores(data.quality_hospital_id, data.quality_state, data.hcahps_measure, data.size, data.offset);
break;
case 'get_asp_pricing':
result = await getAspPricing(data.hcpcs_code_asp, data.quarter);
break;
case 'get_asp_trend':
result = await getAspTrend(data.hcpcs_code_asp, data.start_quarter, data.end_quarter);
break;
case 'compare_asp_pricing':
result = await compareAspPricing(data.hcpcs_codes, data.quarter);
break;
case 'get_formulary_trend':
result = await getFormularyTrend(data.start_month, data.end_month, data.drug_name, data.rxcui, data.trend_metric);
break;
default:
sendError(res, `Unknown method: ${methodName}`, 400);
return;
}
} else {
sendError(res, 'Not found', 404);
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(result));
} catch (err) {
sendError(res, err instanceof Error ? err.message : String(err));
}
} else {
sendError(res, 'Not found', 404);
}
});
server.listen(PORT, () => {
// Server is running
});
}
}
// Handle errors silently using logger
runServer().catch((error) => {
logger.error('Server error:', { error: error instanceof Error ? error.message : String(error) });
process.exit(1);
});