@dw8k/mcp-fallback-server
Version:
MCP fallback server that extracts keywords from prompts and triggers tool recommendations.
84 lines • 3.8 kB
JavaScript
/**
* Implements the core fallback logic using provided ports.
* Assumes dependencies (TagProvider, RecommendationNotifier adapters) are injected.
*/
export class FallbackService {
tagProvider;
recommendationNotifier;
loadedTags = [];
tagsLoaded = false;
constructor(tagProvider, recommendationNotifier) {
this.tagProvider = tagProvider;
this.recommendationNotifier = recommendationNotifier;
}
/**
* Executes the fallback logic: load tags, extract keywords, and notify.
* @param originalQuery The original user query.
*/
async execute(originalQuery) {
// console.log(`[Core Service] Executing fallback for query: "${originalQuery}"`);
try {
await this.ensureTagsLoaded();
}
catch (error) {
console.error("[Core Service] Failed to load tags. Aborting fallback logic.", error);
// Stop execution if tags are essential for the fallback logic to proceed.
return;
}
const keywords = this.extractKeywords(originalQuery, this.loadedTags);
// console.log(`[Core Service] Extracted keywords: ${JSON.stringify(keywords)}`);
if (keywords.length > 0) {
try {
await this.recommendationNotifier.notifyKeywords(keywords);
// console.log("[Core Service] Successfully notified recommendation system.");
}
catch (error) {
console.error("[Core Service] Failed to notify recommendation system.", error);
// Continue execution even if notification fails, as the core logic might still be useful.
}
}
else {
// console.log("[Core Service] No keywords found, skipping notification.");
}
// console.log("[Core Service] Fallback execution finished.");
}
/**
* Ensures tags are loaded into memory, fetching via TagProvider if necessary.
* Uses a simple in-memory flag to avoid redundant fetches within the service instance lifetime.
*/
async ensureTagsLoaded() {
if (!this.tagsLoaded) {
// console.log("[Core Service] Loading tags...");
// Assumes the TagProvider adapter handles the API response structure
// and returns just the array of tag strings.
this.loadedTags = await this.tagProvider.getAllTags();
this.tagsLoaded = true;
// console.log(`[Core Service] Loaded ${this.loadedTags.length} tags.`);
}
else {
// console.log("[Core Service] Tags already loaded.");
}
}
/**
* Extracts keywords by checking for the presence of tags within the query.
* Performs a simple case-insensitive substring match.
* Relies on the TagProvider supplying comprehensive tag variations (e.g., case, synonyms).
* @param query The user's query string.
* @param tags The list of available tags provided by the TagProvider.
* @returns An array of found keywords (maintaining original casing from the tag list).
*/
extractKeywords(query, tags) {
const foundKeywords = [];
const lowerCaseQuery = query.toLowerCase(); // Prepare query for case-insensitive check
for (const tag of tags) {
// Check if the lowercased query includes the lowercased tag
if (lowerCaseQuery.includes(tag.toLowerCase())) {
foundKeywords.push(tag); // Store the original tag casing as the keyword
}
}
// Returns all matches, including potential duplicates if a tag appears multiple times
// or if variations of the same concept (e.g., "notion", "Notion") are matched.
return foundKeywords;
}
}
//# sourceMappingURL=fallback.service.js.map