UNPKG

postgres-mcp-tools

Version:

PostgreSQL-based memory system with vector search capabilities for AI applications, including MCP integration for Claude

122 lines (121 loc) 3.26 kB
import pkg from 'pg'; const { Pool } = pkg; import dotenv from 'dotenv'; import { logger } from '../utils/logger.js'; // Load environment variables dotenv.config(); // Database connection configuration const poolConfig = { user: process.env.POSTGRES_USER || 'memory_user', host: process.env.POSTGRES_HOST || 'localhost', database: process.env.POSTGRES_DB || 'memory_db', password: process.env.POSTGRES_PASSWORD, port: parseInt(process.env.POSTGRES_PORT || '5432', 10), max: parseInt(process.env.PG_MAX_CONNECTIONS || '20', 10), idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, ssl: process.env.POSTGRES_SSL === 'true' ? { rejectUnauthorized: false } : false, }; // Create a connection pool const pool = new Pool(poolConfig); // Pool error handler pool.on('error', (err) => { logger.error('Unexpected error on idle client', err); process.exit(-1); }); /** * Get a client from the pool * @returns A database client */ export const getClient = async () => { try { const client = await pool.connect(); return client; } catch (error) { logger.error('Error connecting to database', error); throw error; } }; /** * Execute a query on the database * @param text The SQL query * @param params The query parameters * @returns The query result */ export const query = async (text, params) => { const start = Date.now(); try { const res = await pool.query(text, params); const duration = Date.now() - start; // Log slow queries for optimization if (duration > 100) { logger.warn(`Slow query (${duration}ms): ${text}`); } return res; } catch (error) { logger.error(`Query error: ${error.message}`, { query: text, params, error: error.stack, }); throw error; } }; /** * Execute a transaction on the database * @param callback The callback function to execute within the transaction * @returns The result of the callback */ export const transaction = async (callback) => { const client = await getClient(); try { await client.query('BEGIN'); const result = await callback(client); await client.query('COMMIT'); return result; } catch (error) { await client.query('ROLLBACK'); logger.error('Transaction error:', error); throw error; } finally { client.release(); } }; /** * Check the health of the database connection * @returns True if the database is healthy, false otherwise */ export const healthCheck = async () => { try { const result = await query('SELECT NOW()'); return result.rows[0] ? true : false; } catch (error) { logger.error('Database health check failed', error); return false; } }; /** * Close the database connection pool */ export const closePool = async () => { try { await pool.end(); logger.info('Database pool closed'); } catch (error) { logger.error('Error closing database pool', error); throw error; } }; export default { query, getClient, transaction, healthCheck, closePool, };