bugger-mcp
Version:
MCP Server for managing bugs, feature requests, and improvements
164 lines • 6.34 kB
JavaScript
// Status normalization utilities for better UX with MCP tool
// Provides fuzzy matching for status values to reduce tool call failures
/**
* Normalize user input status to valid MCP tool status values
*/
export class StatusNormalizer {
static BUG_STATUS_MAPPINGS = {
// Exact matches (case-insensitive)
'open': 'Open',
'in progress': 'In Progress',
'inprogress': 'In Progress',
'in-progress': 'In Progress',
'fixed': 'Fixed',
'closed': 'Closed',
'temporarily resolved': 'Temporarily Resolved',
'temp resolved': 'Temporarily Resolved',
// Common alternatives
'new': 'Open',
'active': 'In Progress',
'working': 'In Progress',
'in work': 'In Progress',
'doing': 'In Progress',
'done': 'Fixed',
'resolved': 'Fixed',
'completed': 'Fixed',
'finished': 'Fixed'
};
static FEATURE_STATUS_MAPPINGS = {
// Exact matches (case-insensitive)
'proposed': 'Proposed',
'in discussion': 'In Discussion',
'indiscussion': 'In Discussion',
'approved': 'Approved',
'in development': 'In Development',
'indevelopment': 'In Development',
'in-development': 'In Development',
'research phase': 'Research Phase',
'research': 'Research Phase',
'partially implemented': 'Partially Implemented',
'partial': 'Partially Implemented',
'completed': 'Completed',
'rejected': 'Rejected',
// Common alternatives
'new': 'Proposed',
'discussing': 'In Discussion',
'accepted': 'Approved',
'working': 'In Development',
'in progress': 'In Development',
'developing': 'In Development',
'building': 'In Development',
'researching': 'Research Phase',
'done': 'Completed',
'finished': 'Completed',
'declined': 'Rejected',
'canceled': 'Rejected',
'cancelled': 'Rejected'
};
static IMPROVEMENT_STATUS_MAPPINGS = {
// Exact matches (case-insensitive)
'proposed': 'Proposed',
'in discussion': 'In Discussion',
'indiscussion': 'In Discussion',
'approved': 'Approved',
'in development': 'In Development',
'indevelopment': 'In Development',
'in-development': 'In Development',
'completed (awaiting human verification)': 'Completed (Awaiting Human Verification)',
'awaiting verification': 'Completed (Awaiting Human Verification)',
'pending verification': 'Completed (Awaiting Human Verification)',
'completed': 'Completed',
'rejected': 'Rejected',
// Common alternatives
'new': 'Proposed',
'discussing': 'In Discussion',
'accepted': 'Approved',
'working': 'In Development',
'in progress': 'In Development',
'developing': 'In Development',
'implementing': 'In Development',
'done': 'Completed',
'finished': 'Completed',
'verified': 'Completed',
'declined': 'Rejected',
'canceled': 'Rejected',
'cancelled': 'Rejected'
};
/**
* Normalize a status string for the given item type
*/
static normalizeStatus(inputStatus, itemType) {
if (!inputStatus || typeof inputStatus !== 'string') {
return null;
}
const normalized = inputStatus.toLowerCase().trim();
let mappings;
switch (itemType) {
case 'bug':
mappings = this.BUG_STATUS_MAPPINGS;
break;
case 'feature':
mappings = this.FEATURE_STATUS_MAPPINGS;
break;
case 'improvement':
mappings = this.IMPROVEMENT_STATUS_MAPPINGS;
break;
default:
return null;
}
return mappings[normalized] || null;
}
/**
* Get all valid status values for an item type
*/
static getValidStatuses(itemType) {
switch (itemType) {
case 'bug':
return ['Open', 'In Progress', 'Fixed', 'Closed', 'Temporarily Resolved'];
case 'feature':
return ['Proposed', 'In Discussion', 'Approved', 'In Development', 'Research Phase', 'Partially Implemented', 'Completed', 'Rejected'];
case 'improvement':
return ['Proposed', 'In Discussion', 'Approved', 'In Development', 'Completed (Awaiting Human Verification)', 'Completed', 'Rejected'];
default:
return [];
}
}
/**
* Generate a helpful error message with valid status suggestions
*/
static generateStatusErrorMessage(inputStatus, itemType) {
const validStatuses = this.getValidStatuses(itemType);
const itemTypeDisplay = itemType.charAt(0).toUpperCase() + itemType.slice(1);
return `Invalid status: "${inputStatus}" for ${itemTypeDisplay} items. Valid statuses are: ${validStatuses.join(', ')}`;
}
/**
* Find the closest matching status using simple string similarity
*/
static suggestClosestStatus(inputStatus, itemType) {
if (!inputStatus)
return null;
const validStatuses = this.getValidStatuses(itemType);
const input = inputStatus.toLowerCase();
// First try exact word matches
for (const status of validStatuses) {
if (status.toLowerCase().includes(input) || input.includes(status.toLowerCase())) {
return status;
}
}
// If no exact match, try normalized mapping
return this.normalizeStatus(inputStatus, itemType);
}
}
/**
* Helper function for MCP tool usage - attempts to normalize status or provides helpful error
*/
export function validateAndNormalizeStatus(inputStatus, itemType) {
const normalized = StatusNormalizer.normalizeStatus(inputStatus, itemType);
if (normalized) {
return { status: normalized, error: null, suggestion: null };
}
const suggestion = StatusNormalizer.suggestClosestStatus(inputStatus, itemType);
const error = StatusNormalizer.generateStatusErrorMessage(inputStatus, itemType);
return { status: null, error, suggestion };
}
//# sourceMappingURL=status-utils.js.map