@1mcp/agent
Version:
One MCP server to aggregate them all - A unified Model Context Protocol server implementation
94 lines (93 loc) • 3.58 kB
JavaScript
import logger from '../logger/logger.js';
import { ConfigChangeEvent, ConfigManager } from '../config/configManager.js';
import { createClients } from '../clients/clientManager.js';
import { setupCapabilities } from '../capabilities/capabilityManager.js';
import { createTransports } from '../config/transportConfig.js';
/**
* Service to handle dynamic configuration reloading
*/
export class ConfigReloadService {
static instance;
serverInfo = null;
currentTransports = {};
isReloading = false;
/**
* Private constructor to enforce singleton pattern
*/
constructor() { }
/**
* Get the singleton instance of the ConfigReloadService
* @returns The ConfigReloadService instance
*/
static getInstance() {
if (!ConfigReloadService.instance) {
ConfigReloadService.instance = new ConfigReloadService();
}
return ConfigReloadService.instance;
}
/**
* Initialize the service with the server instance
* @param serverInfo The MCP server instance
* @param initialTransports The initial transports
*/
initialize(serverInfo, initialTransports) {
this.serverInfo = serverInfo;
this.currentTransports = initialTransports;
const configManager = ConfigManager.getInstance();
// Set up configuration change listener
configManager.on(ConfigChangeEvent.TRANSPORT_CONFIG_CHANGED, this.handleConfigChange.bind(this));
// Start watching for configuration changes
configManager.startWatching();
logger.info('Config reload service initialized');
}
/**
* Handle configuration changes
* @param newConfig The new transport configuration
*/
async handleConfigChange(newConfig) {
if (!this.serverInfo || this.isReloading) {
return;
}
this.isReloading = true;
logger.info('Handling configuration change...');
// Store current transports for reconnection
const currentTransportEntries = Object.entries(this.currentTransports);
try {
// Close all current transports
for (const [key, transport] of currentTransportEntries) {
try {
await transport.close();
logger.info(`Closed transport: ${key}`);
}
catch (error) {
logger.error(`Error closing transport ${key}: ${error}`);
}
}
// Create new transports from updated configuration
const newTransports = createTransports(newConfig);
// Create clients for the new transports
const newClients = await createClients(newTransports);
// Register new capabilities with the server
await setupCapabilities(newClients, this.serverInfo);
// Update current transports
this.currentTransports = newTransports;
logger.info('Configuration reload completed successfully');
}
catch (error) {
logger.error(`Failed to reload configuration: ${error}`);
}
finally {
this.isReloading = false;
}
}
/**
* Stop the service and clean up resources
*/
stop() {
const configManager = ConfigManager.getInstance();
configManager.stopWatching();
configManager.removeAllListeners(ConfigChangeEvent.TRANSPORT_CONFIG_CHANGED);
logger.info('Config reload service stopped');
}
}
export default ConfigReloadService.getInstance();