postgres-mcp-tools
Version:
PostgreSQL-based memory system with vector search capabilities for AI applications, including MCP integration for Claude
133 lines (115 loc) • 4.33 kB
text/typescript
import { Server } from './typescript-sdk-wrapper.js';
import dotenv from 'dotenv';
import { logger } from './utils/logger.js';
import { healthCheck } from './db/client.js';
import { registerResources } from './resources/index.js';
import { registerTools } from './tools/index.js';
import express from 'express';
import { registerGlobalErrorHandlers, tryCatch, errorHandlerMiddleware } from './utils/error-handler.js';
// Load environment variables
dotenv.config();
// Get configuration from environment
const MCP_PORT = parseInt(process.env.MCP_SERVER_PORT || '3000', 10);
const HTTP_PORT = parseInt(process.env.HTTP_PORT || '8080', 10);
const HOST = process.env.MCP_SERVER_HOST || '0.0.0.0';
logger.info('Starting PostgreSQL MCP server...');
logger.debug(`MCP_PORT: ${MCP_PORT}`);
logger.debug(`HTTP_PORT: ${HTTP_PORT}`);
logger.debug(`HOST: ${HOST}`);
// Create the MCP server
const server = new Server({
resources: registerResources(),
tools: registerTools(),
});
// Create an Express app for HTTP endpoints
const app = express();
logger.debug('Express app created');
// Register global error handlers
registerGlobalErrorHandlers();
// Start the server
const startServer = async () => {
return tryCatch(async () => {
// Check database connection
logger.debug('Checking database connection...');
const isHealthy = await healthCheck();
if (!isHealthy) {
logger.error('Database health check failed. Exiting.');
process.exit(1);
}
logger.info('Database connection successful');
// Start the MCP server
logger.debug(`Starting MCP server on ${HOST}:${MCP_PORT}...`);
await server.listen(MCP_PORT, HOST);
logger.info(`MCP Server listening on ${HOST}:${MCP_PORT}`);
logger.info('MCP server started');
// Add error middleware to Express
app.use(errorHandlerMiddleware());
// Add health endpoint
logger.debug('Adding health endpoint...');
app.get('/health', async (req, res, next) => {
try {
logger.debug('Health endpoint requested');
const isHealthy = await healthCheck();
logger.debug(`Health check result: ${isHealthy}`);
if (isHealthy) {
res.status(200).json({ status: 'ok', message: 'Service is healthy' });
} else {
res.status(500).json({ status: 'error', message: 'Service is unhealthy' });
}
} catch (error) {
// Pass error to the error middleware
next(error);
}
});
logger.debug('Health endpoint added');
// Add a simple root endpoint
logger.debug('Adding root endpoint...');
app.get('/', (req, res) => {
logger.debug('Root endpoint requested');
res.status(200).json({
message: 'PostgreSQL MCP Server is running',
version: '1.0.2',
features: ['Robust transport layer', 'Error handling', 'HTTP API']
});
});
logger.debug('Root endpoint added');
// Add version endpoint
app.get('/version', (req, res) => {
res.status(200).json({
version: '1.0.2',
name: 'postgres-memory-mcp',
robustTransport: true,
errorHandling: true
});
});
// Start the Express server on a different port
logger.debug(`Starting Express server on ${HOST}:${HTTP_PORT}...`);
app.listen(HTTP_PORT, HOST, () => {
logger.info(`Express server listening on ${HOST}:${HTTP_PORT}`);
});
// Handle server shutdown
const handleShutdown = async () => {
logger.info('Shutdown requested');
logger.info('Shutting down MCP server...');
await server.close();
// Exit gracefully
setTimeout(() => process.exit(0), 500);
};
// Register shutdown handlers
process.on('SIGINT', handleShutdown);
process.on('SIGTERM', handleShutdown);
logger.debug('Shutdown handlers registered');
}, 'startServer');
};
// Start the server
logger.info('Starting PostgreSQL MCP server with robust transport layer...');
startServer().then(() => {
logger.info('Server started successfully');
logger.info('Robust transport layer initialized successfully');
}).catch((error) => {
logger.error('Failed to start server:', error);
// Don't exit immediately, give it a moment to log the error
setTimeout(() => {
process.exit(1);
}, 1000);
});