@xiaohui-wang/mcpadvisor
Version:
MCP Advisor & Installation - Find the right MCP server for your needs
234 lines (233 loc) • 9.5 kB
JavaScript
/**
* Factory for creating and managing MCP search providers
* Centralizes search functionality for different MCP search providers
*/
import { SearchService } from '../../searchService.js';
import { OfflineSearchProvider } from './OfflineSearchProvider.js';
import { GetMcpSearchProvider } from './GetMcpSearchProvider.js';
import { CompassSearchProvider } from './CompassSearchProvider.js';
import { MeilisearchSearchProvider } from './MeilisearchSearchProvider.js';
import { NacosMcpProvider } from './NacosMcpProvider.js';
import logger from '../../../utils/logger.js';
/**
* Search using the Offline provider
* @param query Search query or params
* @param options Search options
* @param fallbackDataPath Path to fallback data
* @param textMatchWeight Weight for text matching (default: 0.7)
* @returns Array of MCP server responses
*/
export async function searchOffline(query, options = {}, fallbackDataPath, textMatchWeight = 0.7) {
const searchParams = typeof query === 'string'
? { taskDescription: query }
: query;
try {
logger.info(`Searching offline with query: "${query}"`, 'OfflineSearch', {
query,
options,
});
const startTime = Date.now();
const provider = new OfflineSearchProvider({
fallbackDataPath,
minSimilarity: options.minSimilarity || 0.3,
textMatchWeight,
vectorSearchWeight: 1 - textMatchWeight,
});
logger.debug('Using OfflineSearchProvider', 'OfflineSearch');
const service = new SearchService([provider]);
const results = await service.search(searchParams, options);
const duration = Date.now() - startTime;
logger.info(`Offline search completed in ${duration}ms with ${results.length} results`, 'OfflineSearch', {
duration,
resultCount: results.length,
});
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error searching offline: ${errorMessage}`, 'OfflineSearch', {
error: errorMessage,
});
throw error;
}
}
/**
* Search using the GetMCP provider
* @param query Search query or params
* @param options Search options
* @returns Array of MCP server responses
*/
export async function searchGetMcp(query, options = {}) {
const searchParams = typeof query === 'string'
? { taskDescription: query }
: query;
try {
logger.info(`Searching GetMCP with query: "${query}"`, 'GetMcpSearch', {
query,
options,
});
const provider = new GetMcpSearchProvider();
logger.debug('Created GetMcpSearchProvider instance', 'GetMcpSearch');
const service = new SearchService([provider]);
logger.debug('Created SearchService with GetMcpSearchProvider', 'GetMcpSearch');
const startTime = Date.now();
const results = await service.search(searchParams, options);
const duration = Date.now() - startTime;
logger.info(`GetMCP search completed in ${duration}ms with ${results.length} results`, 'GetMcpSearch', {
duration,
resultCount: results.length,
});
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error searching GetMCP: ${errorMessage}`, 'GetMcpSearch', {
error: errorMessage,
});
throw error;
}
}
/**
* Search using the Compass provider
* @param query Search query or params
* @param options Search options
* @returns Array of MCP server responses
*/
export async function searchCompass(query, options = {}) {
const searchParams = typeof query === 'string'
? { taskDescription: query }
: query;
try {
logger.info(`Searching Compass with query: "${query}"`, 'CompassSearch', {
query,
options,
});
const provider = new CompassSearchProvider();
logger.debug('Created CompassSearchProvider instance', 'CompassSearch');
const service = new SearchService([provider]);
logger.debug('Created SearchService with CompassSearchProvider', 'CompassSearch');
const startTime = Date.now();
const results = await service.search(searchParams, options);
const duration = Date.now() - startTime;
logger.info(`Compass search completed in ${duration}ms with ${results.length} results`, 'CompassSearch', {
duration,
resultCount: results.length,
});
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error searching Compass: ${errorMessage}`, 'CompassSearch', {
error: errorMessage,
});
throw error;
}
}
/**
* Search using the Meilisearch provider
* @param query Search query or params
* @param options Search options
* @returns Array of MCP server responses
*/
export async function searchMeilisearch(query, options = {}) {
const searchParams = typeof query === 'string'
? { taskDescription: query }
: query;
try {
logger.info(`Searching Meilisearch with query: "${query}"`, 'MeilisearchSearch', { query, options });
const provider = new MeilisearchSearchProvider();
logger.debug('Created MeilisearchSearchProvider instance', 'MeilisearchSearch');
const service = new SearchService([provider]);
logger.debug('Created SearchService with MeilisearchSearchProvider', 'MeilisearchSearch');
const startTime = Date.now();
const results = await service.search(searchParams, options);
const duration = Date.now() - startTime;
logger.info(`Meilisearch search completed in ${duration}ms with ${results.length} results`, 'MeilisearchSearch', {
duration,
resultCount: results.length,
});
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error searching Meilisearch: ${errorMessage}`, 'MeilisearchSearch', { error: errorMessage });
throw error;
}
}
/**
* Factory function to get a search function by provider name
* @param providerName Name of the provider ('offline', 'getmcp', 'compass', 'meilisearch')
* @returns The corresponding search function
*/
/**
* Search using the Nacos MCP provider
* @param query Search query or params
* @param options Search options
* @param config Nacos MCP provider configuration
* @returns Array of MCP server responses
*/
export async function searchNacosMcp(query, options = {}, config) {
const searchParams = typeof query === 'string'
? { taskDescription: query }
: query;
try {
logger.info(`Searching Nacos MCP with query: "${query}"`, 'NacosMcpSearch', {
query,
options,
});
const startTime = Date.now();
const provider = new NacosMcpProvider({
...config,
minSimilarity: options.minSimilarity || 0.3,
limit: options.limit || 10,
debug: process.env.NODE_ENV === 'development',
});
logger.debug('Using NacosMcpProvider', 'NacosMcpSearch');
const service = new SearchService([provider]);
const results = await service.search(searchParams, options);
const duration = Date.now() - startTime;
logger.info(`Nacos MCP search completed in ${duration}ms with ${results.length} results`, 'NacosMcpSearch', {
duration,
resultCount: results.length,
});
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error searching Nacos MCP: ${errorMessage}`, 'NacosMcpSearch', {
error: errorMessage,
});
throw error;
}
}
export function getSearchFunction(providerName) {
const normalizedProviderName = providerName.toLowerCase();
switch (normalizedProviderName) {
case 'offline':
return searchOffline;
case 'getmcp':
return searchGetMcp;
case 'compass':
return searchCompass;
case 'meilisearch':
return searchMeilisearch;
case 'nacos':
case 'nacos-mcp':
return (query, options = {}) => {
// Create config with required fields and optional authToken
const config = {
serverAddr: process.env.NACOS_SERVER_ADDR || 'http://localhost:8848',
username: process.env.NACOS_USERNAME || 'nacos',
password: process.env.NACOS_PASSWORD || 'nacos',
mcpHost: process.env.MCP_HOST || 'localhost',
mcpPort: process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : 3000,
authToken: options.authToken || process.env.MCP_AUTH_TOKEN || '',
};
// Remove authToken from options to avoid passing it twice
const { authToken, ...searchOptions } = options;
return searchNacosMcp(query, searchOptions, config);
};
default:
throw new Error(`Unknown search provider: ${providerName}`);
}
}