#!/usr/bin/env node /** * Israel Law MCP Server -- stdio entry point. * * Provides Israeli legislation search via Model Context Protocol. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import Database from '@ansvar/mcp-sqlite'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import { createHash } from 'crypto'; import { readFileSync } from 'fs'; import { registerTools, type AboutContext } from './tools/registry.js'; import { detectCapabilities, readDbMetadata } from './capabilities.js'; import { DB_ENV_VAR, SERVER_NAME, SERVER_VERSION, } from './constants.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); function resolveDbPath(): string { if (process.env[DB_ENV_VAR]) { return process.env[DB_ENV_VAR]; } return join(__dirname, '..', 'data', 'database.db'); } let db: InstanceType | null = null; function getDb(): InstanceType { if (!db) { const dbPath = resolveDbPath(); db = new Database(dbPath, { readonly: true }); db.pragma('foreign_keys = ON'); const caps = detectCapabilities(db); const meta = readDbMetadata(db); console.error(`[${SERVER_NAME}] DB opened: tier=${meta.tier}, caps=[${[...caps].join(',')}]`); } return db; } function computeAboutContext(): AboutContext { const dbPath = resolveDbPath(); let fingerprint = 'unknown'; let dbBuilt = 'unknown'; try { const buf = readFileSync(dbPath); fingerprint = createHash('sha256').update(buf).digest('hex').slice(0, 12); } catch { // DB might not exist in dev } try { const database = getDb(); const row = database.prepare("SELECT value FROM db_metadata WHERE key = 'built_at'").get() as { value: string } | undefined; if (row) dbBuilt = row.value; } catch { // Ignore } return { version: SERVER_VERSION, fingerprint, dbBuilt }; } async function main() { const database = getDb(); const aboutContext = computeAboutContext(); const server = new Server( { name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } } ); registerTools(server, database, aboutContext); const transport = new StdioServerTransport(); await server.connect(transport); console.error(`[${SERVER_NAME}] Server running on stdio`); const cleanup = () => { if (db) { db.close(); db = null; } process.exit(0); }; process.on('SIGINT', cleanup); process.on('SIGTERM', cleanup); } main().catch((err) => { console.error(`[${SERVER_NAME}] Fatal error:`, err); process.exit(1); });