UNPKG

dhis2-mcp-server

Version:

A Model Context Protocol server providing 108 tools for DHIS2 development, including code generators, debugging helpers, and documentation access for web and Android app development.

293 lines 13.6 kB
export class ParameterCompletion { dhis2Client; constructor(dhis2Client) { this.dhis2Client = dhis2Client; } async getCompletion(toolName, argumentName, partialValue) { if (!this.dhis2Client) { return { values: [] }; } try { switch (argumentName) { case 'dataElement': case 'dataElementId': return await this.getDataElementCompletions(partialValue); case 'orgUnit': case 'organisationUnit': case 'orgUnitId': return await this.getOrganisationUnitCompletions(partialValue); case 'period': return this.getPeriodCompletions(); case 'categoryOptionCombo': return await this.getCategoryOptionComboCompletions(partialValue); case 'program': case 'programId': return await this.getProgramCompletions(partialValue); case 'trackedEntityType': return await this.getTrackedEntityTypeCompletions(partialValue); case 'valueType': return this.getValueTypeCompletions(); case 'domainType': return this.getDomainTypeCompletions(); case 'aggregationType': return this.getAggregationTypeCompletions(); case 'periodType': return this.getPeriodTypeCompletions(); default: return { values: [] }; } } catch (error) { console.error(`Error getting completion for ${argumentName}:`, error); return { values: [] }; } } async getDataElementCompletions(partialValue) { const params = { pageSize: 50, fields: 'id,displayName,valueType,domainType' }; if (partialValue) { params.filter = `name:ilike:${partialValue}`; } const response = await this.dhis2Client.getDataElements(params); return { values: response.dataElements.map(de => ({ value: de.id, label: de.displayName, description: `${de.valueType} - ${de.domainType}` })) }; } async getOrganisationUnitCompletions(partialValue) { const params = { pageSize: 50, fields: 'id,displayName,level,path' }; if (partialValue) { params.filter = `name:ilike:${partialValue}`; } const response = await this.dhis2Client.getOrganisationUnits(params); return { values: response.organisationUnits.map(ou => ({ value: ou.id, label: ou.displayName, description: `Level ${ou.level} - ${ou.path?.split('/').length - 1} parents` })) }; } getPeriodCompletions() { const currentYear = new Date().getFullYear(); const values = []; // Current and previous years (yearly periods) for (let year = currentYear; year >= currentYear - 3; year--) { values.push({ value: year.toString(), label: `Year ${year}`, description: 'Yearly period' }); // Quarterly periods for (let q = 1; q <= 4; q++) { values.push({ value: `${year}Q${q}`, label: `Q${q} ${year}`, description: 'Quarterly period' }); } // Monthly periods for (let m = 1; m <= 12; m++) { const month = m.toString().padStart(2, '0'); values.push({ value: `${year}${month}`, label: `${year}-${month}`, description: 'Monthly period' }); } } return { values: values.slice(0, 50) }; // Limit to 50 most recent } async getCategoryOptionComboCompletions(partialValue) { const params = { pageSize: 30, fields: 'id,displayName' }; if (partialValue) { params.filter = `name:ilike:${partialValue}`; } const response = await this.dhis2Client.getCategoryOptionCombos(params); return { values: response.categoryOptionCombos.map(coc => ({ value: coc.id, label: coc.displayName, description: 'Category option combination' })) }; } async getProgramCompletions(partialValue) { const params = { pageSize: 30, fields: 'id,displayName,programType' }; if (partialValue) { params.filter = `name:ilike:${partialValue}`; } const response = await this.dhis2Client.getPrograms(params); return { values: response.programs.map(program => ({ value: program.id, label: program.displayName, description: program.programType || 'Program' })) }; } async getTrackedEntityTypeCompletions(partialValue) { const params = { pageSize: 30, fields: 'id,displayName' }; if (partialValue) { params.filter = `name:ilike:${partialValue}`; } const response = await this.dhis2Client.getTrackedEntityTypes(params); return { values: response.trackedEntityTypes.map(tet => ({ value: tet.id, label: tet.displayName, description: 'Tracked entity type' })) }; } getValueTypeCompletions() { return { values: [ { value: 'TEXT', label: 'Text', description: 'Free text input' }, { value: 'LONG_TEXT', label: 'Long Text', description: 'Multi-line text input' }, { value: 'NUMBER', label: 'Number', description: 'Numeric value with decimals' }, { value: 'INTEGER', label: 'Integer', description: 'Whole numbers only' }, { value: 'INTEGER_POSITIVE', label: 'Positive Integer', description: 'Positive whole numbers only' }, { value: 'INTEGER_NEGATIVE', label: 'Negative Integer', description: 'Negative whole numbers only' }, { value: 'INTEGER_ZERO_OR_POSITIVE', label: 'Zero or Positive Integer', description: 'Zero or positive whole numbers' }, { value: 'PERCENTAGE', label: 'Percentage', description: 'Percentage value (0-100)' }, { value: 'BOOLEAN', label: 'Yes/No', description: 'True/false value' }, { value: 'TRUE_ONLY', label: 'Yes Only', description: 'Only true values allowed' }, { value: 'DATE', label: 'Date', description: 'Date value' }, { value: 'DATETIME', label: 'Date & Time', description: 'Date and time value' }, { value: 'TIME', label: 'Time', description: 'Time value' }, { value: 'EMAIL', label: 'Email', description: 'Email address' }, { value: 'PHONE_NUMBER', label: 'Phone Number', description: 'Phone number' }, { value: 'URL', label: 'URL', description: 'Web address' }, { value: 'FILE_RESOURCE', label: 'File', description: 'File attachment' }, { value: 'COORDINATE', label: 'Coordinate', description: 'GPS coordinates' }, { value: 'ORGANISATION_UNIT', label: 'Organisation Unit', description: 'Organisation unit reference' }, { value: 'REFERENCE', label: 'Reference', description: 'Reference to another object' }, { value: 'AGE', label: 'Age', description: 'Age in years' } ] }; } getDomainTypeCompletions() { return { values: [ { value: 'AGGREGATE', label: 'Aggregate', description: 'For aggregate data collection' }, { value: 'TRACKER', label: 'Tracker', description: 'For individual tracking programs' } ] }; } getAggregationTypeCompletions() { return { values: [ { value: 'SUM', label: 'Sum', description: 'Add all values' }, { value: 'AVERAGE', label: 'Average', description: 'Calculate mean value' }, { value: 'AVERAGE_SUM_ORG_UNIT', label: 'Average (Sum in Org Unit)', description: 'Average across periods, sum across org units' }, { value: 'COUNT', label: 'Count', description: 'Count number of values' }, { value: 'STDDEV', label: 'Standard Deviation', description: 'Statistical standard deviation' }, { value: 'VARIANCE', label: 'Variance', description: 'Statistical variance' }, { value: 'MIN', label: 'Minimum', description: 'Lowest value' }, { value: 'MAX', label: 'Maximum', description: 'Highest value' }, { value: 'NONE', label: 'None', description: 'No aggregation' } ] }; } getPeriodTypeCompletions() { return { values: [ { value: 'Daily', label: 'Daily', description: 'Daily periods' }, { value: 'Weekly', label: 'Weekly', description: 'Weekly periods' }, { value: 'WeeklyWednesday', label: 'Weekly (Wednesday)', description: 'Weekly starting Wednesday' }, { value: 'WeeklyThursday', label: 'Weekly (Thursday)', description: 'Weekly starting Thursday' }, { value: 'WeeklySaturday', label: 'Weekly (Saturday)', description: 'Weekly starting Saturday' }, { value: 'WeeklySunday', label: 'Weekly (Sunday)', description: 'Weekly starting Sunday' }, { value: 'BiWeekly', label: 'Bi-Weekly', description: '2-week periods' }, { value: 'Monthly', label: 'Monthly', description: 'Monthly periods' }, { value: 'BiMonthly', label: 'Bi-Monthly', description: '2-month periods' }, { value: 'Quarterly', label: 'Quarterly', description: 'Quarterly periods' }, { value: 'SixMonthly', label: 'Six Monthly', description: '6-month periods' }, { value: 'SixMonthlyApril', label: 'Six Monthly (April)', description: '6-month starting April' }, { value: 'SixMonthlyNov', label: 'Six Monthly (November)', description: '6-month starting November' }, { value: 'Yearly', label: 'Yearly', description: 'Yearly periods' }, { value: 'FinancialApril', label: 'Financial Year (April)', description: 'Financial year starting April' }, { value: 'FinancialJuly', label: 'Financial Year (July)', description: 'Financial year starting July' }, { value: 'FinancialOct', label: 'Financial Year (October)', description: 'Financial year starting October' }, { value: 'FinancialNov', label: 'Financial Year (November)', description: 'Financial year starting November' } ] }; } // Tool-specific completions async getToolSpecificCompletion(toolName, argumentName, context) { switch (toolName) { case 'dhis2_create_data_value': if (argumentName === 'categoryOptionCombo' && context.dataElement) { // Get category combos specific to the data element return await this.getCategoryComboForDataElement(context.dataElement); } break; case 'dhis2_create_event': if (argumentName === 'orgUnit' && context.program) { // Get org units assigned to the program return await this.getOrgUnitsForProgram(context.program); } break; } return { values: [] }; } async getCategoryComboForDataElement(dataElementId) { try { // Since getDataElement doesn't exist, we'll use a generic completion const response = await this.dhis2Client.getCategoryOptionCombos({ pageSize: 20, fields: 'id,displayName' }); return { values: response.categoryOptionCombos.map((coc) => ({ value: coc.id, label: coc.displayName, description: 'Category option combination' })) }; } catch (error) { console.warn('Could not fetch category combos for data element:', error); } return { values: [] }; } async getOrgUnitsForProgram(programId) { try { // Since getProgram doesn't exist, we'll use a generic completion const response = await this.dhis2Client.getOrganisationUnits({ pageSize: 20, fields: 'id,displayName,level' }); return { values: response.organisationUnits.map((ou) => ({ value: ou.id, label: ou.displayName, description: `Level ${ou.level} - Organization unit` })) }; } catch (error) { console.warn('Could not fetch org units for program:', error); } return { values: [] }; } } //# sourceMappingURL=parameter-completion.js.map