Skip to main content
Glama
IBM
by IBM
index.ts6.23 kB
import { config } from "@/config/index.js"; import { ToolProcessor } from "./utils/config/toolProcessor.js"; import { ToolConfigCache } from "./utils/config/toolConfigCache.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { logger, requestContextService, RequestContext, } from "@/utils/internal/index.js"; // Store server replacement callback for auto-reload let serverReplacementCallback: ((newServer: McpServer) => void) | null = null; // Global cache for YAML tool configurations let cachedToolConfigs: ToolConfigCache | null = null; // Global tool processor instance let toolProcessor: ToolProcessor | null = null; /** * Set the server replacement callback for auto-reload functionality * This should be called by transport managers that support server replacement */ export const setServerReplacementCallback = ( callback: (newServer: McpServer) => void, ): void => { serverReplacementCallback = callback; logger.debug( {}, "Server replacement callback registered for YAML auto-reload", ); }; export const registerSQLTools = async (server: McpServer): Promise<void> => { // Load YAML tools if configured if (config.toolsYamlPath) { const context = requestContextService.createRequestContext({ operation: "registerSQLTools", yamlPath: config.toolsYamlPath, }); // Check if we have cached tool configs if (cachedToolConfigs && !cachedToolConfigs.isEmpty()) { logger.info( context, `Registering ${cachedToolConfigs.getStats().toolCount} cached YAML tools (cache hit)`, ); // Register tools from cache - this is extremely fast await cachedToolConfigs.registerCachedTools(server, context); return; } logger.info( context, `Processing YAML tools from configuration: ${config.toolsYamlPath} (auto-reload: ${config.yamlAutoReload})`, ); // Initialize processor if needed if (!toolProcessor) { toolProcessor = new ToolProcessor(); } // Initialize cache if needed if (!cachedToolConfigs) { cachedToolConfigs = ToolConfigCache.getInstance(); } try { // Simple 3-step workflow: initialize → process → register await toolProcessor.initialize(context); const processingResult = await toolProcessor.processTools(context); if (processingResult.success) { // Cache the processed tool configurations const toolConfigs = toolProcessor.getToolConfigurations(); const cacheResult = cachedToolConfigs.cacheToolConfigs( toolConfigs, context, ); if (cacheResult.success) { logger.info( context, `YAML tools processed and cached: ${cacheResult.toolCount} tools, ${cacheResult.toolsetCount} toolsets`, ); // Register with server await toolProcessor.registerWithServer(server, context); // Setup auto-reload if enabled if (config.yamlAutoReload) { await setupAutoReload(server, context); } } else { logger.error( context, `Failed to cache tool configurations: ${cacheResult.error}`, ); throw new Error(`Tool caching failed: ${cacheResult.error}`); } } else { logger.error( context, `Failed to process YAML tools: ${processingResult.error}`, ); throw new Error( `YAML tools processing failed: ${processingResult.error}`, ); } } catch (error) { logger.error( context, `Error processing YAML tools: ${error instanceof Error ? error.message : String(error)}`, ); throw error; } } else { logger.debug( {}, "No YAML tools configuration found, skipping YAML tools loading", ); } }; /** * Setup auto-reload functionality for YAML configuration changes * @param server - MCP server instance * @param context - Request context * @private */ async function setupAutoReload( server: McpServer, context: RequestContext, ): Promise<void> { const { ToolProcessor } = await import("./utils/config/toolProcessor.js"); ToolProcessor.registerChangeCallback( async (filePath, eventType, changeContext) => { const rebuildContext = changeContext || requestContextService.createRequestContext({ operation: "AutoReloadOnFileChange", filePath, eventType, }); logger.info( rebuildContext, `YAML file changed (${eventType}): ${filePath} - rebuilding tools`, ); try { // Create new processor for rebuild const newProcessor = new ToolProcessor(); await newProcessor.initialize(rebuildContext); const result = await newProcessor.processTools(rebuildContext); if (result.success) { // Update cache with new configurations const toolConfigs = newProcessor.getToolConfigurations(); const cacheResult = cachedToolConfigs!.cacheToolConfigs( toolConfigs, rebuildContext, ); if (cacheResult.success) { logger.info( rebuildContext, `Tools rebuilt successfully: ${cacheResult.toolCount} tools, ${cacheResult.toolsetCount} toolsets`, ); // Update global processor reference toolProcessor = newProcessor; // Call server replacement callback if available if (serverReplacementCallback) { serverReplacementCallback(server); } } else { logger.error( rebuildContext, `Failed to cache rebuilt tools: ${cacheResult.error}`, ); } } else { logger.error( rebuildContext, `Failed to rebuild tools: ${result.error}`, ); } } catch (error) { logger.error( rebuildContext, `Error during auto-reload: ${error instanceof Error ? error.message : String(error)}`, ); } }, ); logger.info(context, "YAML auto-reload functionality enabled"); }

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/IBM/ibmi-mcp'

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