postgres-mcp-tools
Version:
PostgreSQL-based memory system with vector search capabilities for AI applications, including MCP integration for Claude
206 lines (185 loc) • 6.49 kB
JavaScript
import http from 'http';
import pkg from 'pg';
const { Pool } = pkg;
import dotenv from 'dotenv';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// Get the directory name
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Load environment variables
dotenv.config();
// Log the current directory and environment variables
console.log(`Current directory: ${__dirname}`);
console.log(`POSTGRES_USER: ${process.env.POSTGRES_USER}`);
console.log(`POSTGRES_HOST: ${process.env.POSTGRES_HOST}`);
console.log(`POSTGRES_DB: ${process.env.POSTGRES_DB}`);
console.log(`POSTGRES_PORT: ${process.env.POSTGRES_PORT}`);
console.log(`Password length: ${process.env.POSTGRES_PASSWORD ? process.env.POSTGRES_PASSWORD.length : 0}`);
// Create a PostgreSQL connection pool
const pool = new Pool({
user: 'memory_user',
host: '127.0.0.1', // Connect to the Docker container's PostgreSQL server
database: 'memory_db',
password: "#9H{+GOc$|J,tAJQt894e:vV=PZ-CI&>", // Hardcoded for testing
port: 5432,
});
// Health check server info endpoint
const healthInfo = {
message: 'PostgreSQL MCP Health Check Server',
endpoints: {
'/': 'Server information',
'/health': 'Database health check endpoint',
'/docker-health': 'Docker container health check'
}
};
// Create an HTTP server
const server = http.createServer(async (req, res) => {
console.log(`Request received: ${req.method} ${req.url}`);
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// Handle OPTIONS request for CORS preflight
if (req.method === 'OPTIONS') {
res.statusCode = 204;
res.end();
return;
}
// Handle GET requests to the health endpoint
if (req.method === 'GET' && req.url === '/health') {
try {
// Check database connection
console.log('Executing database query...');
const result = await pool.query('SELECT NOW()');
console.log('Query result:', result.rows[0]);
if (result.rows[0]) {
// Database is healthy
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'ok',
message: 'Service is healthy',
timestamp: new Date().toISOString()
}));
} else {
// Database query returned no results
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'error',
message: 'Database query returned no results'
}));
}
} catch (error) {
// Database connection failed
console.error('Health check failed:', error);
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'error',
message: `Database connection failed: ${error.message}`
}));
}
return;
}
// Handle GET requests to the docker-health endpoint
if (req.method === 'GET' && req.url === '/docker-health') {
try {
// Run a command to check if Docker containers are running
const { execSync } = await import('child_process');
try {
const output = execSync('docker ps | grep postgres-mcp-tools').toString();
console.log('Docker ps output:', output);
// Check if both containers are running
const mcpServerRunning = output.includes('mcp-server');
const postgresRunning = output.includes('memory-postgres');
if (mcpServerRunning && postgresRunning) {
// Both containers are running
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'ok',
message: 'Docker containers are running',
mcp_server: true,
postgres: true,
timestamp: new Date().toISOString()
}));
} else {
// Some containers are not running
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'error',
message: 'Some Docker containers are not running',
mcp_server: mcpServerRunning,
postgres: postgresRunning
}));
}
} catch (error) {
// Docker command failed
console.error('Docker check failed:', error);
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'error',
message: 'Failed to check Docker containers'
}));
}
} catch (error) {
// Child process import failed
console.error('Docker check failed:', error);
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'error',
message: 'Failed to import child_process module'
}));
}
return;
}
// Handle GET requests to the root
if (req.method === 'GET' && req.url === '/') {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(healthInfo));
return;
}
// Handle all other requests
res.statusCode = 404;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ error: 'Not Found' }));
});
// Start the server
const PORT = 6060;
const HOST = '0.0.0.0';
server.listen(PORT, HOST, () => {
console.log(`Health check server listening on ${HOST}:${PORT}`);
console.log('Available endpoints:');
Object.entries(healthInfo.endpoints).forEach(([endpoint, description]) => {
console.log(` ${endpoint}: ${description}`);
});
});
// Handle server shutdown
process.on('SIGINT', () => {
console.log('Shutting down health check server...');
server.close(() => {
console.log('Health check server closed');
pool.end(() => {
console.log('Database pool closed');
process.exit(0);
});
});
});
process.on('SIGTERM', () => {
console.log('Shutting down health check server...');
server.close(() => {
console.log('Health check server closed');
pool.end(() => {
console.log('Database pool closed');
process.exit(0);
});
});
});