Skip to main content
Glama
search-tools.ts8.9 kB
/** * Search Tools - MCP tools for searching aggregated tools */ import type { ToolMetadata, ToolImplementation } from '../types.js'; import { SearchEngine, type SearchOptions, type SearchResponse } from './search-engine.js'; import type { AggregatedToolMetadata } from '../mcp/mcp-client-manager.js'; /** * Create search tool metadata */ export function createSearchToolMetadata(): ToolMetadata { return { name: 'search_tools', description: 'Search for tools by name or description. Supports multiple search modes: partial (default), prefix, exact, and fuzzy matching.', parameters: [ { name: 'query', type: 'string', description: 'Search query text', required: true, minLength: 1, }, { name: 'mode', type: 'string', description: 'Search mode: partial (contains), prefix (starts with), exact (exact match), or fuzzy (similarity-based)', required: false, enum: ['partial', 'prefix', 'exact', 'fuzzy'], default: 'partial', }, { name: 'caseSensitive', type: 'boolean', description: 'Whether the search should be case-sensitive', required: false, default: false, }, { name: 'searchFields', type: 'array', description: 'Fields to search in: name, description, or both', required: false, }, { name: 'limit', type: 'number', description: 'Maximum number of results to return', required: false, minimum: 1, maximum: 100, default: 50, }, { name: 'offset', type: 'number', description: 'Number of results to skip (for pagination)', required: false, minimum: 0, default: 0, }, ], }; } /** * Create advanced search tool metadata */ export function createAdvancedSearchToolMetadata(): ToolMetadata { return { name: 'advanced_search', description: 'Advanced search with filtering by server, tags, and categories. Combines text search with filters for precise results.', parameters: [ { name: 'query', type: 'string', description: 'Search query text (optional if using filters)', required: false, }, { name: 'serverName', type: 'string', description: 'Filter by MCP server name', required: false, }, { name: 'tags', type: 'array', description: 'Filter by tags (matches any of the provided tags)', required: false, }, { name: 'category', type: 'string', description: 'Filter by category', required: false, }, { name: 'mode', type: 'string', description: 'Search mode for text query', required: false, enum: ['partial', 'prefix', 'exact', 'fuzzy'], default: 'partial', }, { name: 'limit', type: 'number', description: 'Maximum number of results', required: false, minimum: 1, maximum: 100, default: 50, }, { name: 'offset', type: 'number', description: 'Pagination offset', required: false, minimum: 0, default: 0, }, ], }; } /** * Create search tool implementation */ export function createSearchToolImplementation( getTools: () => AggregatedToolMetadata[] ): ToolImplementation { return async (parameters: Record<string, any>) => { const tools = getTools(); const options: SearchOptions = { mode: parameters.mode || 'partial', caseSensitive: parameters.caseSensitive || false, searchFields: parameters.searchFields || ['name', 'description'], limit: parameters.limit || 50, offset: parameters.offset || 0, }; const response = SearchEngine.search(tools, parameters.query, options); // Format results for MCP return { results: response.results.map(result => ({ name: result.item.name, description: result.item.description, serverName: result.item.serverName, originalName: result.item.originalName, score: result.score, matches: result.matches, })), total: response.total, limit: response.limit, offset: response.offset, query: response.query, }; }; } /** * Create advanced search tool implementation */ export function createAdvancedSearchToolImplementation( getTools: () => AggregatedToolMetadata[] ): ToolImplementation { return async (parameters: Record<string, any>) => { let tools = getTools(); // Apply filters if (parameters.serverName) { tools = tools.filter(tool => tool.serverName === parameters.serverName); } if (parameters.tags && Array.isArray(parameters.tags)) { // Note: This requires tools to have tags in their metadata // For now, we'll skip this filter as tags aren't in the current schema console.warn('Tag filtering not yet implemented - tags not in tool metadata'); } if (parameters.category) { // Note: This requires tools to have category in their metadata // For now, we'll skip this filter as category isn't in the current schema console.warn('Category filtering not yet implemented - category not in tool metadata'); } // Apply text search if query provided if (parameters.query) { const options: SearchOptions = { mode: parameters.mode || 'partial', caseSensitive: false, searchFields: ['name', 'description'], limit: parameters.limit || 50, offset: parameters.offset || 0, }; const response = SearchEngine.search(tools, parameters.query, options); return { results: response.results.map(result => ({ name: result.item.name, description: result.item.description, serverName: result.item.serverName, originalName: result.item.originalName, score: result.score, matches: result.matches, })), total: response.total, limit: response.limit, offset: response.offset, query: response.query, filters: { serverName: parameters.serverName, tags: parameters.tags, category: parameters.category, }, }; } else { // No text search, just return filtered results const limit = parameters.limit || 50; const offset = parameters.offset || 0; const total = tools.length; const paginatedTools = tools.slice(offset, offset + limit); return { results: paginatedTools.map(tool => ({ name: tool.name, description: tool.description, serverName: tool.serverName, originalName: tool.originalName, score: 0, })), total, limit, offset, query: '', filters: { serverName: parameters.serverName, tags: parameters.tags, category: parameters.category, }, }; } }; } /** * Create list servers tool metadata */ export function createListServersToolMetadata(): ToolMetadata { return { name: 'list_servers', description: 'List all connected MCP servers with their status and tool counts', parameters: [], }; } /** * Create list servers tool implementation */ export function createListServersToolImplementation( getStats: () => any ): ToolImplementation { return async () => { const stats = getStats(); return { totalServers: stats.totalServers, runningServers: stats.runningServers, totalTools: stats.totalTools, servers: stats.servers.map((server: any) => ({ name: server.name, running: server.running, toolCount: server.toolCount, reconnectionStatus: server.reconnectionStatus, })), }; }; } /** * Create health check tool metadata */ export function createHealthCheckToolMetadata(): ToolMetadata { return { name: 'health_check', description: 'Check the health status of the Search MCP Server, including memory usage, server status, cache performance, and configuration', parameters: [ { name: 'detailed', type: 'boolean', description: 'Return detailed health information with all checks', required: false, default: false, }, ], }; } /** * Create health check tool implementation */ export function createHealthCheckToolImplementation( healthChecker: any ): ToolImplementation { return async (parameters: Record<string, any>) => { const detailed = parameters.detailed || false; if (detailed) { return await healthChecker.check(); } else { return await healthChecker.quickCheck(); } }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/krtw00/search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server