Skip to main content
Glama

1MCP Server

server.ts7.47 kB
import { McpConfigManager } from '@src/config/mcpConfigManager.js'; import { MCP_SERVER_CAPABILITIES, MCP_SERVER_NAME, MCP_SERVER_VERSION } from '@src/constants.js'; import { AgentConfigManager } from '@src/core/server/agentConfig.js'; import logger, { debugIf } from '@src/logger/logger.js'; import configReloadService from './application/services/configReloadService.js'; import { AsyncLoadingOrchestrator } from './core/capabilities/asyncLoadingOrchestrator.js'; import { ClientManager } from './core/client/clientManager.js'; import { InstructionAggregator } from './core/instructions/instructionAggregator.js'; import { McpLoadingManager } from './core/loading/mcpLoadingManager.js'; import { ServerManager } from './core/server/serverManager.js'; import { PresetManager } from './domains/preset/manager/presetManager.js'; import { PresetNotificationService } from './domains/preset/services/presetNotificationService.js'; import { createTransports } from './transport/transportFactory.js'; /** * Result of server setup including both sync and async components */ export interface ServerSetupResult { /** Server manager ready for HTTP transport */ serverManager: ServerManager; /** Loading manager for async MCP server initialization */ loadingManager: McpLoadingManager; /** Promise that resolves when all MCP servers finish loading */ loadingPromise: Promise<void>; /** Async loading orchestrator (only present in async mode) */ asyncOrchestrator?: AsyncLoadingOrchestrator; /** Instruction aggregator for combining server instructions */ instructionAggregator: InstructionAggregator; } /** * Main function to set up the MCP server * Conditionally uses async or legacy loading based on configuration */ async function setupServer(): Promise<ServerSetupResult> { try { const mcpConfig = McpConfigManager.getInstance().getTransportConfig(); const agentConfig = AgentConfigManager.getInstance(); const asyncLoadingEnabled = agentConfig.isAsyncLoadingEnabled(); // Initialize preset management system await initializePresetSystem(); // Create transports from configuration const transports = createTransports(mcpConfig); logger.info(`Created ${Object.keys(transports).length} transports`); if (asyncLoadingEnabled) { logger.info('Using async loading mode - HTTP server will start immediately, MCP servers load in background'); return setupServerAsync(transports); } else { logger.info('Using legacy synchronous loading mode - waiting for all MCP servers before starting HTTP server'); return setupServerSync(transports); } } catch (error) { logger.error(`Failed to set up server: ${error}`); throw error; } } /** * Set up server with async loading (new mode) * HTTP server starts immediately, MCP servers load in background */ async function setupServerAsync(transports: Record<string, any>): Promise<ServerSetupResult> { // Initialize instruction aggregator const instructionAggregator = new InstructionAggregator(); logger.info('Instruction aggregator initialized'); // Initialize client manager without connecting (for async loading) const clientManager = ClientManager.getOrCreateInstance(); clientManager.setInstructionAggregator(instructionAggregator); const clients = clientManager.initializeClientsAsync(transports); logger.info(`Initialized storage for ${Object.keys(transports).length} MCP servers`); // Create server manager with empty clients initially const serverManager = ServerManager.getOrCreateInstance( { name: MCP_SERVER_NAME, version: MCP_SERVER_VERSION }, { capabilities: MCP_SERVER_CAPABILITIES }, clients, transports, ); serverManager.setInstructionAggregator(instructionAggregator); // Initialize config reload service configReloadService.initialize(transports); // Create loading manager for async MCP server initialization const loadingManager = new McpLoadingManager(clientManager); // Create async loading orchestrator for capability tracking and notifications const asyncOrchestrator = new AsyncLoadingOrchestrator(clients, serverManager, loadingManager); asyncOrchestrator.initialize(); // Start async loading (non-blocking) const loadingPromise = loadingManager .startAsyncLoading(transports) .then(() => { logger.info('All MCP servers finished loading (successfully or failed)'); }) .catch((error) => { logger.error('MCP loading process encountered an error:', error); }); logger.info('Async server setup completed - HTTP server ready, MCP servers loading in background'); return { serverManager, loadingManager, loadingPromise, asyncOrchestrator, instructionAggregator, }; } /** * Set up server with legacy synchronous loading * Waits for all MCP servers to load before returning */ async function setupServerSync(transports: Record<string, any>): Promise<ServerSetupResult> { // Initialize instruction aggregator const instructionAggregator = new InstructionAggregator(); logger.info('Instruction aggregator initialized'); // Use the standard synchronous client creation const clientManager = ClientManager.getOrCreateInstance(); clientManager.setInstructionAggregator(instructionAggregator); const clients = await clientManager.createClients(transports); logger.info(`Connected to ${clients.size} MCP servers synchronously`); // Create server manager with connected clients const serverManager = ServerManager.getOrCreateInstance( { name: MCP_SERVER_NAME, version: MCP_SERVER_VERSION }, { capabilities: MCP_SERVER_CAPABILITIES }, clients, transports, ); serverManager.setInstructionAggregator(instructionAggregator); // Initialize config reload service configReloadService.initialize(transports); // Create a dummy loading manager for compatibility const loadingManager = new McpLoadingManager(clientManager); const loadingPromise = Promise.resolve(); // Already loaded logger.info('Synchronous server setup completed - all MCP servers connected'); return { serverManager, loadingManager, loadingPromise, instructionAggregator, }; } /** * Initialize the preset management system */ async function initializePresetSystem(): Promise<void> { try { // Initialize preset manager with file watching const presetManager = PresetManager.getInstance(); await presetManager.initialize(); // Initialize notification service const notificationService = PresetNotificationService.getInstance(); // Connect preset changes to client notifications presetManager.onPresetChange(async (presetName: string) => { debugIf(() => ({ message: 'Preset changed, sending notifications', meta: { presetName, timestamp: Date.now() }, })); await notificationService.notifyPresetChange(presetName); }); logger.info('Preset management system initialized successfully'); } catch (error) { logger.error('Failed to initialize preset system', { error }); throw error; } } /** * Legacy function for backward compatibility * @deprecated Use setupServer() which returns ServerSetupResult */ async function setupServerLegacy(): Promise<ServerManager> { const result = await setupServer(); // Wait for loading to complete for legacy behavior await result.loadingPromise; return result.serverManager; } export { setupServer, setupServerLegacy };

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/1mcp-app/agent'

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