Files
Momento/mcp-server/index.js
Sepehr Ramezani e4d4e23dc7 chore: clean up repo for public release
- Remove BMAD framework, IDE configs, dev screenshots, test files,
  internal docs, and backup files
- Rename keep-notes/ to memento-note/
- Update all references from keep-notes to memento-note
- Add Apache 2.0 license with Commons Clause (non-commercial restriction)
- Add clean .gitignore and .env.docker.example
2026-04-20 22:48:06 +02:00

130 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Memento MCP Server - Stdio Transport (Optimized)
*
* Performance improvements:
* - Prisma connection pooling
* - Prepared statements caching
* - Optimized JSON serialization
* - Lazy user resolution
*
* Environment variables:
* DATABASE_URL - Prisma database URL (default: ../../memento-note/prisma/dev.db)
* USER_ID - Optional user ID to filter data
* APP_BASE_URL - Optional Next.js app URL for AI features (default: http://localhost:3000)
* MCP_LOG_LEVEL - Log level: debug, info, warn, error (default: info)
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { PrismaClient } from '../memento-note/prisma/client-generated/index.js';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { registerTools } from './tools.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Configuration
const LOG_LEVEL = process.env.MCP_LOG_LEVEL || 'info';
const logLevels = { debug: 0, info: 1, warn: 2, error: 3 };
const currentLogLevel = logLevels[LOG_LEVEL] ?? 1;
function log(level, ...args) {
if (logLevels[level] >= currentLogLevel) {
console.error(`[${level.toUpperCase()}]`, ...args);
}
}
// Database - requires DATABASE_URL environment variable
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
console.error('ERROR: DATABASE_URL environment variable is required');
process.exit(1);
}
// OPTIMIZED: Prisma client with connection pooling and prepared statements
const prisma = new PrismaClient({
datasources: {
db: { url: databaseUrl },
},
// SQLite optimizations
log: LOG_LEVEL === 'debug' ? ['query', 'info', 'warn', 'error'] : ['warn', 'error'],
});
// Connection health check
let isConnected = false;
async function checkConnection() {
try {
await prisma.$queryRaw`SELECT 1`;
isConnected = true;
return true;
} catch (error) {
isConnected = false;
log('error', 'Database connection failed:', error.message);
return false;
}
}
const server = new Server(
{
name: 'memento-mcp-server',
version: '3.1.0',
},
{
capabilities: { tools: {} },
},
);
const appBaseUrl = process.env.APP_BASE_URL || 'http://localhost:3000';
registerTools(server, prisma, {
userId: process.env.USER_ID || null,
appBaseUrl,
});
async function main() {
// Verify database connection on startup
const connected = await checkConnection();
if (!connected) {
console.error('FATAL: Could not connect to database');
process.exit(1);
}
const transport = new StdioServerTransport();
await server.connect(transport);
log('info', `Memento MCP Server v3.1.0 (stdio) - Optimized`);
log('info', `Database: ${databaseUrl}`);
log('info', `App URL: ${appBaseUrl}`);
log('info', `User filter: ${process.env.USER_ID || 'none (all data)'}`);
log('debug', 'Performance optimizations enabled: connection pooling, batch operations, caching');
}
main().catch((error) => {
console.error('Server error:', error);
process.exit(1);
});
// Graceful shutdown
process.on('SIGINT', async () => {
log('info', 'Shutting down gracefully...');
await prisma.$disconnect();
process.exit(0);
});
process.on('SIGTERM', async () => {
log('info', 'Shutting down gracefully...');
await prisma.$disconnect();
process.exit(0);
});
// Handle uncaught errors
process.on('uncaughtException', (error) => {
log('error', 'Uncaught exception:', error.message);
});
process.on('unhandledRejection', (reason) => {
log('error', 'Unhandled rejection:', reason);
});