elasticsearch-mcp
Version:
Secure MCP server for Elasticsearch integration with comprehensive tools and Elastic Cloud support
163 lines • 5.91 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElasticsearchManager = void 0;
const elasticsearch_1 = require("@elastic/elasticsearch");
class ElasticsearchManager {
client = null;
config;
logger;
connectionInfo;
healthCheckInterval = null;
constructor(config, logger) {
this.config = config;
this.logger = logger.child({ component: 'elasticsearch' });
this.connectionInfo = {
isConnected: false,
lastHealthCheck: new Date(),
};
}
async initialize() {
try {
this.logger.info('Initializing Elasticsearch client', {
cloudId: this.config.cloudId ? '***' : undefined,
node: this.config.node,
hasApiKey: !!this.config.apiKey,
hasAuth: !!this.config.auth,
});
const clientOptions = {
maxRetries: this.config.maxRetries,
requestTimeout: this.config.requestTimeout,
pingTimeout: this.config.pingTimeout,
sniffOnStart: this.config.sniffOnStart,
...(this.config.sniffInterval && { sniffInterval: this.config.sniffInterval }),
};
if (this.config.cloudId) {
clientOptions.cloud = { id: this.config.cloudId };
if (this.config.apiKey) {
clientOptions.auth = { apiKey: this.config.apiKey };
}
}
else if (this.config.node) {
clientOptions.node = this.config.node;
if (this.config.apiKey) {
clientOptions.auth = { apiKey: this.config.apiKey };
}
else if (this.config.auth) {
clientOptions.auth = {
username: this.config.auth.username,
password: this.config.auth.password,
};
}
}
if (this.config.ssl) {
clientOptions.tls = {
rejectUnauthorized: this.config.ssl.rejectUnauthorized,
};
}
this.client = new elasticsearch_1.Client(clientOptions);
await this.healthCheck();
this.startHealthMonitoring();
this.logger.info('Elasticsearch client initialized successfully', {
clusterName: this.connectionInfo.clusterName,
version: this.connectionInfo.version,
});
}
catch (error) {
this.logger.error('Failed to initialize Elasticsearch client', {}, error);
throw error;
}
}
async healthCheck() {
if (!this.client) {
this.connectionInfo = {
isConnected: false,
lastHealthCheck: new Date(),
error: 'Client not initialized',
};
return false;
}
try {
const [pingResult, infoResult] = await Promise.all([
this.client.ping(),
this.client.info(),
]);
this.connectionInfo = {
isConnected: pingResult === true,
clusterName: infoResult.cluster_name,
version: infoResult.version?.number,
lastHealthCheck: new Date(),
};
if (this.connectionInfo.isConnected) {
this.logger.debug('Health check passed', {
clusterName: this.connectionInfo.clusterName,
version: this.connectionInfo.version,
});
}
return this.connectionInfo.isConnected;
}
catch (error) {
this.connectionInfo = {
isConnected: false,
lastHealthCheck: new Date(),
error: error.message,
};
this.logger.warn('Health check failed', {
error: error.message,
});
return false;
}
}
async reconnect() {
this.logger.info('Attempting to reconnect to Elasticsearch');
if (this.client) {
await this.client.close();
}
await this.initialize();
}
getClient() {
if (!this.client) {
throw new Error('Elasticsearch client not initialized');
}
if (!this.connectionInfo.isConnected) {
throw new Error('Elasticsearch client not connected');
}
return this.client;
}
getConnectionInfo() {
return { ...this.connectionInfo };
}
startHealthMonitoring() {
const HEALTH_CHECK_INTERVAL = 30000; // 30 seconds
this.healthCheckInterval = setInterval(async () => {
const isHealthy = await this.healthCheck();
if (!isHealthy) {
this.logger.warn('Health check failed, attempting reconnection');
try {
await this.reconnect();
}
catch (error) {
this.logger.error('Reconnection failed', {}, error);
}
}
}, HEALTH_CHECK_INTERVAL);
}
async shutdown() {
this.logger.info('Shutting down Elasticsearch manager');
if (this.healthCheckInterval) {
clearInterval(this.healthCheckInterval);
this.healthCheckInterval = null;
}
if (this.client) {
try {
await this.client.close();
this.logger.info('Elasticsearch client closed');
}
catch (error) {
this.logger.warn('Error closing Elasticsearch client', { error: error.message });
}
}
this.connectionInfo.isConnected = false;
}
}
exports.ElasticsearchManager = ElasticsearchManager;
//# sourceMappingURL=client.js.map