falkordb-mcpserver
Version:
Model Context Protocol server for FalkorDB graph databases - enables AI assistants to query and manage graph data using natural language
129 lines (128 loc) • 5.26 kB
JavaScript
import { FalkorDB } from 'falkordb';
import { config } from '../config/index.js';
import { AppError, CommonErrors } from '../errors/AppError.js';
import { logger } from './logger.service.js';
class FalkorDBService {
client = null;
maxRetries = 5;
retryCount = 0;
isInitializing = false;
constructor() {
// Don't initialize in constructor - use explicit initialization
}
async initialize() {
if (this.isInitializing) {
return;
}
this.isInitializing = true;
try {
logger.info('Attempting to connect to FalkorDB', {
host: config.falkorDB.host,
port: config.falkorDB.port,
attempt: this.retryCount + 1
});
this.client = await FalkorDB.connect({
socket: {
host: config.falkorDB.host,
port: config.falkorDB.port,
},
password: config.falkorDB.password,
username: config.falkorDB.username,
});
// Test connection
const connection = await this.client.connection;
await connection.ping();
logger.info('Successfully connected to FalkorDB');
this.retryCount = 0;
this.isInitializing = false;
}
catch (error) {
this.isInitializing = false;
if (this.retryCount < this.maxRetries) {
this.retryCount++;
logger.warn('Failed to connect to FalkorDB, retrying...', {
attempt: this.retryCount,
maxRetries: this.maxRetries,
error: error instanceof Error ? error.message : String(error)
});
await new Promise(resolve => setTimeout(resolve, 5000));
return this.initialize();
}
else {
const appError = new AppError(CommonErrors.CONNECTION_FAILED, `Failed to connect to FalkorDB after ${this.maxRetries} attempts: ${error instanceof Error ? error.message : String(error)}`, true);
logger.error('FalkorDB connection failed permanently', appError);
throw appError;
}
}
}
async executeQuery(graphName, query, params) {
if (!this.client) {
throw new AppError(CommonErrors.CONNECTION_FAILED, 'FalkorDB client not initialized. Call initialize() first.', true);
}
try {
const graph = this.client.selectGraph(graphName);
const result = await graph.query(query, params);
logger.debug('Query executed successfully', {
graphName,
query: query.substring(0, 100) + (query.length > 100 ? '...' : ''),
hasParams: !!params
});
return result;
}
catch (error) {
const appError = new AppError(CommonErrors.OPERATION_FAILED, `Failed to execute query on graph '${graphName}': ${error instanceof Error ? error.message : String(error)}`, true);
logger.error('Query execution failed', appError, { graphName, query });
throw appError;
}
}
/**
* Lists all available graphs in FalkorDB
* @returns Array of graph names
*/
async listGraphs() {
if (!this.client) {
throw new AppError(CommonErrors.CONNECTION_FAILED, 'FalkorDB client not initialized. Call initialize() first.', true);
}
try {
const graphs = await this.client.list();
logger.debug('Listed graphs successfully', { count: graphs.length });
return graphs;
}
catch (error) {
const appError = new AppError(CommonErrors.OPERATION_FAILED, `Failed to list graphs: ${error instanceof Error ? error.message : String(error)}`, true);
logger.error('Failed to list graphs', appError);
throw appError;
}
}
async deleteGraph(graphName) {
if (!this.client) {
throw new AppError(CommonErrors.CONNECTION_FAILED, 'FalkorDB client not initialized. Call initialize() first.', true);
}
try {
await this.client.selectGraph(graphName).delete();
logger.info('Graph deleted successfully', { graphName });
}
catch (error) {
const appError = new AppError(CommonErrors.OPERATION_FAILED, `Failed to delete graph '${graphName}': ${error instanceof Error ? error.message : String(error)}`, true);
logger.error('Failed to delete graph', appError, { graphName });
throw appError;
}
}
async close() {
if (this.client) {
try {
await this.client.close();
logger.info('FalkorDB connection closed successfully');
}
catch (error) {
logger.error('Error closing FalkorDB connection', error instanceof Error ? error : new Error(String(error)));
}
finally {
this.client = null;
this.retryCount = 0;
}
}
}
}
// Export a singleton instance
export const falkorDBService = new FalkorDBService();