@adevguide/mcp-database-server 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/types.ts","../src/utils.ts","../src/adapters/postgres.ts","../src/logger.ts","../src/adapters/base.ts","../src/adapters/mysql.ts","../src/adapters/sqlite.ts","../src/adapters/mssql.ts","../src/adapters/oracle.ts","../src/adapters/index.ts","../src/cache.ts","../src/query-tracker.ts","../src/database-manager.ts","../src/mcp-server.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport dotenv from 'dotenv';\nimport { parseArgs } from 'util';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { loadConfig, findConfigFile } from './config.js';\nimport { DatabaseManager } from './database-manager.js';\nimport { MCPServer } from './mcp-server.js';\nimport { initLogger, getLogger } from './logger.js';\n\n// Load environment variables\ndotenv.config();\n\n// Get package version\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\nconst version = packageJson.version;\n\nasync function main() {\n try {\n // Parse command line arguments\n const { values } = parseArgs({\n options: {\n config: {\n type: 'string',\n short: 'c',\n default: './.mcp-database-server.config',\n },\n help: {\n type: 'boolean',\n short: 'h',\n },\n version: {\n type: 'boolean',\n short: 'v',\n },\n },\n });\n\n if (values.version) {\n console.log(version);\n process.exit(0);\n }\n\n if (values.help) {\n console.log(`\nmcp-database-server - Model Context Protocol Server for SQL Databases\n\nUsage:\n mcp-database-server [options]\n\nOptions:\n -c, --config <path> Path to configuration file (default: ./.mcp-database-server.config)\n -h, --help Show this help message\n -v, --version Show version number\n\nConfiguration:\n The config file should be a JSON file with database configurations.\n See mcp-database-server.config.example for reference.\n\nEnvironment Variables:\n You can use environment variable interpolation in the config file:\n Example: \"url\": \"\\${DB_URL_POSTGRES}\"\n\nExamples:\n mcp-database-server --config ./my-config.json\n mcp-database-server -c ./config/production.json\n `);\n process.exit(0);\n }\n\n // Load configuration\n let configPath = values.config as string;\n \n // If config path is the default, try to find it by traversing up\n if (configPath === './.mcp-database-server.config') {\n const foundPath = findConfigFile('.mcp-database-server.config');\n if (foundPath) {\n configPath = foundPath;\n } else {\n console.error('Error: Config file .mcp-database-server.config not found');\n console.error('Searched in current directory and all parent directories');\n console.error('\\nTo create a config file:');\n console.error(' cp mcp-database-server.config.example .mcp-database-server.config');\n console.error('\\nOr specify a custom path:');\n console.error(' mcp-database-server --config /path/to/config.json');\n process.exit(1);\n }\n }\n \n const config = await loadConfig(configPath);\n\n // Initialize logger\n initLogger(config.logging?.level || 'info', config.logging?.pretty || false);\n const logger = getLogger();\n\n logger.info({ configPath }, 'Configuration loaded');\n\n // Initialize database manager\n const dbManager = new DatabaseManager(config.databases, {\n cacheDir: config.cache?.directory || '.sql-mcp-cache',\n cacheTtlMinutes: config.cache?.ttlMinutes || 10,\n allowWrite: config.security?.allowWrite || false,\n allowedWriteOperations: config.security?.allowedWriteOperations,\n disableDangerousOperations: config.security?.disableDangerousOperations ?? true,\n });\n\n await dbManager.init();\n\n // Create and start MCP server\n const mcpServer = new MCPServer(dbManager, config);\n await mcpServer.start();\n\n // Graceful shutdown\n const shutdown = async (signal: string) => {\n logger.info({ signal }, 'Shutting down...');\n await dbManager.shutdown();\n process.exit(0);\n };\n\n process.on('SIGINT', () => shutdown('SIGINT'));\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n } catch (error: any) {\n console.error('Fatal error:', error.message);\n if (error.details) {\n console.error('Details:', JSON.stringify(error.details, null, 2));\n }\n process.exit(1);\n }\n}\n\nmain();\n","import fs from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname, resolve, join } from 'path';\nimport { ServerConfig, ServerConfigSchema, ConfigError } from './types.js';\nimport { interpolateEnv } from './utils.js';\n\n/**\n * Find config file by traversing up the directory tree\n * @param fileName - Name of the config file to find\n * @param startDir - Directory to start searching from (defaults to cwd)\n * @returns Absolute path to config file or null if not found\n */\nexport function findConfigFile(fileName: string, startDir: string = process.cwd()): string | null {\n let currentDir = resolve(startDir);\n\n while (true) {\n const configPath = join(currentDir, fileName);\n \n if (existsSync(configPath)) {\n return configPath;\n }\n\n const parentDir = dirname(currentDir);\n \n // Reached filesystem root (parent equals current)\n if (parentDir === currentDir) {\n break;\n }\n\n // Move up one directory\n currentDir = parentDir;\n }\n\n return null;\n}\n\nexport async function loadConfig(configPath: string): Promise<ServerConfig> {\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const rawConfig = JSON.parse(content);\n\n // Interpolate environment variables in all string values\n const interpolatedConfig = interpolateConfigValues(rawConfig);\n\n // Validate with Zod\n const config = ServerConfigSchema.parse(interpolatedConfig);\n\n // Additional validation\n validateDatabaseConfigs(config);\n\n return config;\n } catch (error: any) {\n if (error.name === 'ZodError') {\n throw new ConfigError('Configuration validation failed', error.errors);\n }\n throw new ConfigError(`Failed to load config from ${configPath}: ${error.message}`);\n }\n}\n\nfunction interpolateConfigValues(obj: any): any {\n if (typeof obj === 'string') {\n return interpolateEnv(obj);\n }\n \n if (Array.isArray(obj)) {\n return obj.map(interpolateConfigValues);\n }\n \n if (obj && typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = interpolateConfigValues(value);\n }\n return result;\n }\n \n return obj;\n}\n\nfunction validateDatabaseConfigs(config: ServerConfig): void {\n const ids = new Set<string>();\n\n for (const db of config.databases) {\n // Check for duplicate IDs\n if (ids.has(db.id)) {\n throw new ConfigError(`Duplicate database ID: ${db.id}`);\n }\n ids.add(db.id);\n\n // Validate database-specific requirements\n if (db.type === 'sqlite') {\n if (!db.path && !db.url) {\n throw new ConfigError(`SQLite database ${db.id} requires 'path' or 'url'`);\n }\n } else {\n if (!db.url) {\n throw new ConfigError(`Database ${db.id} requires 'url'`);\n }\n }\n }\n}\n","import { z } from 'zod';\n\n// Database types\nexport type DatabaseType = 'postgres' | 'mysql' | 'mssql' | 'sqlite' | 'oracle';\n\n// Connection pool settings\nexport const ConnectionPoolSchema = z.object({\n min: z.number().min(0).optional(),\n max: z.number().min(1).optional(),\n idleTimeoutMillis: z.number().min(0).optional(),\n connectionTimeoutMillis: z.number().min(0).optional(),\n});\n\nexport type ConnectionPool = z.infer<typeof ConnectionPoolSchema>;\n\n// Introspection options\nexport const IntrospectionOptionsSchema = z.object({\n includeViews: z.boolean().optional().default(true),\n includeRoutines: z.boolean().optional().default(false),\n maxTables: z.number().min(1).optional(),\n excludeSchemas: z.array(z.string()).optional(),\n includeSchemas: z.array(z.string()).optional(),\n});\n\nexport type IntrospectionOptions = z.infer<typeof IntrospectionOptionsSchema>;\n\n// Database configuration\nexport const DatabaseConfigSchema = z.object({\n id: z.string().min(1),\n type: z.enum(['postgres', 'mysql', 'mssql', 'sqlite', 'oracle']),\n url: z.string().optional(),\n path: z.string().optional(),\n readOnly: z.boolean().optional().default(true),\n pool: ConnectionPoolSchema.optional(),\n introspection: IntrospectionOptionsSchema.optional(),\n eagerConnect: z.boolean().optional().default(false),\n});\n\nexport type DatabaseConfig = z.infer<typeof DatabaseConfigSchema>;\n\n// Server configuration\nexport const ServerConfigSchema = z.object({\n databases: z.array(DatabaseConfigSchema).min(1),\n cache: z\n .object({\n directory: z.string().optional().default('.sql-mcp-cache'),\n ttlMinutes: z.number().min(0).optional().default(10),\n })\n .optional()\n .default({ directory: '.sql-mcp-cache', ttlMinutes: 10 }),\n security: z\n .object({\n allowWrite: z.boolean().optional().default(false),\n allowedWriteOperations: z.array(z.string()).optional(),\n disableDangerousOperations: z.boolean().optional().default(true),\n redactSecrets: z.boolean().optional().default(true),\n })\n .optional()\n .default({ allowWrite: false, disableDangerousOperations: true, redactSecrets: true }),\n logging: z\n .object({\n level: z.enum(['trace', 'debug', 'info', 'warn', 'error']).optional().default('info'),\n pretty: z.boolean().optional().default(false),\n })\n .optional()\n .default({ level: 'info', pretty: false }),\n});\n\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\n\n// Schema metadata types\nexport interface ColumnMetadata {\n name: string;\n dataType: string;\n nullable: boolean;\n defaultValue?: string;\n maxLength?: number;\n precision?: number;\n scale?: number;\n isAutoIncrement?: boolean;\n comment?: string;\n}\n\nexport interface IndexMetadata {\n name: string;\n columns: string[];\n isUnique: boolean;\n isPrimary: boolean;\n}\n\nexport interface ForeignKeyMetadata {\n name: string;\n columns: string[];\n referencedSchema: string;\n referencedTable: string;\n referencedColumns: string[];\n onDelete?: string;\n onUpdate?: string;\n}\n\nexport interface TableMetadata {\n schema: string;\n name: string;\n type: 'table' | 'view';\n columns: ColumnMetadata[];\n primaryKey?: IndexMetadata;\n indexes: IndexMetadata[];\n foreignKeys: ForeignKeyMetadata[];\n comment?: string;\n}\n\nexport interface SchemaMetadata {\n name: string;\n tables: TableMetadata[];\n}\n\nexport interface DatabaseSchema {\n dbId: string;\n dbType: DatabaseType;\n schemas: SchemaMetadata[];\n introspectedAt: Date;\n version: string; // ETag/version based on content\n}\n\n// Relationship types\nexport interface Relationship {\n fromSchema: string;\n fromTable: string;\n fromColumns: string[];\n toSchema: string;\n toTable: string;\n toColumns: string[];\n type: 'foreign_key' | 'inferred';\n confidence?: number; // For inferred relationships\n}\n\n// Query result types\nexport interface QueryResult {\n rows: any[];\n columns: string[];\n rowCount: number;\n executionTimeMs: number;\n affectedRows?: number;\n}\n\nexport interface ExplainResult {\n plan: any;\n formattedPlan?: string;\n}\n\n// Query tracking\nexport interface QueryHistoryEntry {\n timestamp: Date;\n sql: string;\n tables: string[];\n executionTimeMs: number;\n rowCount: number;\n error?: string;\n}\n\n// Join suggestion\nexport interface JoinPath {\n tables: string[];\n joins: Array<{\n fromTable: string;\n toTable: string;\n relationship: Relationship;\n joinCondition: string;\n }>;\n}\n\n// Database adapter interface\nexport interface DatabaseAdapter {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n introspect(options?: IntrospectionOptions): Promise<DatabaseSchema>;\n query(sql: string, params?: any[], timeoutMs?: number): Promise<QueryResult>;\n explain(sql: string, params?: any[]): Promise<ExplainResult>;\n testConnection(): Promise<boolean>;\n getVersion(): Promise<string>;\n}\n\n// Error types\nexport class DatabaseError extends Error {\n constructor(\n message: string,\n public _code: string,\n public _dbId?: string,\n public _originalError?: Error\n ) {\n super(message);\n this.name = 'DatabaseError';\n }\n}\n\nexport class ConfigError extends Error {\n constructor(message: string, public _details?: any) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nexport class CacheError extends Error {\n constructor(message: string, public _originalError?: Error) {\n super(message);\n this.name = 'CacheError';\n }\n}\n","import crypto from 'crypto';\nimport { URL } from 'url';\nimport { Relationship, DatabaseSchema } from './types.js';\n\n/**\n * Redact secrets from URLs and connection strings\n */\nexport function redactUrl(url: string): string {\n try {\n // Handle various URL formats\n if (url.includes('://')) {\n const urlObj = new URL(url);\n if (urlObj.password) {\n urlObj.password = '***';\n }\n if (urlObj.username && urlObj.password) {\n return urlObj.toString();\n }\n }\n \n // Handle SQL Server connection strings\n if (url.includes('Password=')) {\n return url.replace(/(Password=)[^;]+/gi, '$1***');\n }\n \n // Handle Oracle connection strings\n if (url.includes('/') && url.includes('@')) {\n return url.replace(/\\/[^@]+@/, '/***@');\n }\n \n return url;\n } catch {\n // If parsing fails, be safe and redact everything after ://\n return url.replace(/:\\/\\/[^@]*@/, '://***@');\n }\n}\n\n/**\n * Interpolate environment variables in config values\n */\nexport function interpolateEnv(value: string): string {\n return value.replace(/\\$\\{([^}]+)\\}/g, (_, varName) => {\n return process.env[varName] || '';\n });\n}\n\n/**\n * Generate a stable version/ETag from schema content\n */\nexport function generateSchemaVersion(schema: DatabaseSchema): string {\n const hash = crypto.createHash('sha256');\n \n // Create a stable representation of the schema\n const schemaData = {\n dbType: schema.dbType,\n schemas: schema.schemas.map((s) => ({\n name: s.name,\n tables: s.tables\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((t) => ({\n name: t.name,\n type: t.type,\n columns: t.columns\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((c) => ({\n name: c.name,\n dataType: c.dataType,\n nullable: c.nullable,\n })),\n foreignKeys: t.foreignKeys.sort((a, b) => a.name.localeCompare(b.name)),\n })),\n })),\n };\n \n hash.update(JSON.stringify(schemaData));\n return hash.digest('hex').substring(0, 16);\n}\n\n/**\n * Infer relationships from column naming patterns\n */\nexport function inferRelationships(schema: DatabaseSchema): Relationship[] {\n const relationships: Relationship[] = [];\n \n // Build a lookup of tables and their primary keys\n const tableLookup = new Map<string, { schema: string; pk: string[] }>();\n \n for (const schemaObj of schema.schemas) {\n for (const table of schemaObj.tables) {\n const fullName = `${schemaObj.name}.${table.name}`;\n const pk = table.primaryKey?.columns || [];\n tableLookup.set(table.name.toLowerCase(), { schema: schemaObj.name, pk });\n tableLookup.set(fullName.toLowerCase(), { schema: schemaObj.name, pk });\n }\n }\n \n // Look for FK patterns in each table\n for (const schemaObj of schema.schemas) {\n for (const table of schemaObj.tables) {\n for (const column of table.columns) {\n const columnName = column.name.toLowerCase();\n \n // Pattern 1: <table>_id or <table>Id\n const patterns = [\n /^(.+?)_id$/,\n /^(.+?)id$/i,\n ];\n \n for (const pattern of patterns) {\n const match = columnName.match(pattern);\n if (match) {\n const referencedTableName = match[1].toLowerCase();\n const referencedTable = tableLookup.get(referencedTableName);\n \n if (referencedTable && referencedTable.pk.length > 0) {\n // Only infer if we have a reasonable confidence\n relationships.push({\n fromSchema: schemaObj.name,\n fromTable: table.name,\n fromColumns: [column.name],\n toSchema: referencedTable.schema,\n toTable: referencedTableName,\n toColumns: referencedTable.pk,\n type: 'inferred',\n confidence: 0.7,\n });\n }\n }\n }\n }\n }\n }\n \n return relationships;\n}\n\n/**\n * Extract table names from SQL (best effort)\n */\nexport function extractTableNames(sql: string): string[] {\n const tables = new Set<string>();\n \n // Simple regex-based extraction (best effort)\n // Matches: FROM table, JOIN table, INTO table, UPDATE table, DELETE FROM table\n const patterns = [\n /(?:FROM|JOIN|INTO|UPDATE)\\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)?)/gi,\n /DELETE\\s+FROM\\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)?)/gi,\n ];\n \n for (const pattern of patterns) {\n const matches = sql.matchAll(pattern);\n for (const match of matches) {\n if (match[1]) {\n tables.add(match[1].toLowerCase());\n }\n }\n }\n \n return Array.from(tables);\n}\n\n/**\n * Detect if SQL is a write operation\n */\nexport function isWriteOperation(sql: string): boolean {\n const upperSql = sql.trim().toUpperCase();\n const writeKeywords = [\n 'INSERT',\n 'UPDATE',\n 'DELETE',\n 'CREATE',\n 'ALTER',\n 'DROP',\n 'TRUNCATE',\n 'REPLACE',\n 'MERGE',\n ];\n \n for (const keyword of writeKeywords) {\n if (upperSql.startsWith(keyword)) {\n return true;\n }\n }\n \n return false;\n}\n\n/**\n * Find join paths between tables using relationship graph\n */\nexport function findJoinPaths(\n tables: string[],\n relationships: Relationship[],\n maxDepth = 3\n): any[] {\n if (tables.length < 2) {\n return [];\n }\n \n const paths: any[] = [];\n \n // Build adjacency list\n const graph = new Map<string, Relationship[]>();\n for (const rel of relationships) {\n const fromKey = `${rel.fromSchema}.${rel.fromTable}`.toLowerCase();\n const toKey = `${rel.toSchema}.${rel.toTable}`.toLowerCase();\n \n if (!graph.has(fromKey)) {\n graph.set(fromKey, []);\n }\n graph.get(fromKey)!.push(rel);\n \n // Reverse direction\n const reverseRel: Relationship = {\n ...rel,\n fromSchema: rel.toSchema,\n fromTable: rel.toTable,\n fromColumns: rel.toColumns,\n toSchema: rel.fromSchema,\n toTable: rel.fromTable,\n toColumns: rel.fromColumns,\n };\n \n if (!graph.has(toKey)) {\n graph.set(toKey, []);\n }\n graph.get(toKey)!.push(reverseRel);\n }\n \n // Simple BFS to find shortest path between first two tables\n const start = tables[0].toLowerCase();\n const end = tables[1].toLowerCase();\n \n const queue: Array<{ current: string; path: Relationship[] }> = [{ current: start, path: [] }];\n const visited = new Set<string>([start]);\n \n while (queue.length > 0) {\n const { current, path } = queue.shift()!;\n \n if (path.length >= maxDepth) {\n continue;\n }\n \n const neighbors = graph.get(current) || [];\n for (const rel of neighbors) {\n const next = `${rel.toSchema}.${rel.toTable}`.toLowerCase();\n \n if (next === end) {\n paths.push({\n tables: [start, ...path.map((r) => `${r.toSchema}.${r.toTable}`), end],\n joins: [...path, rel],\n });\n continue;\n }\n \n if (!visited.has(next)) {\n visited.add(next);\n queue.push({ current: next, path: [...path, rel] });\n }\n }\n }\n \n return paths;\n}\n","import pg from 'pg';\nimport { BaseAdapter } from './base.js';\nimport {\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n TableMetadata,\n ColumnMetadata,\n IndexMetadata,\n ForeignKeyMetadata,\n SchemaMetadata,\n} from '../types.js';\nimport { generateSchemaVersion } from '../utils.js';\n\nconst { Pool } = pg;\n\nexport class PostgresAdapter extends BaseAdapter {\n private pool?: pg.Pool;\n\n async connect(): Promise<void> {\n try {\n this.pool = new Pool({\n connectionString: this._config.url,\n min: this._config.pool?.min || 2,\n max: this._config.pool?.max || 10,\n idleTimeoutMillis: this._config.pool?.idleTimeoutMillis || 30000,\n connectionTimeoutMillis: this._config.pool?.connectionTimeoutMillis || 10000,\n });\n\n // Test connection\n const client = await this.pool.connect();\n client.release();\n\n this.connected = true;\n this.logger.info({ dbId: this._config.id }, 'PostgreSQL connected');\n } catch (error) {\n this.handleError(error, 'connect');\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = undefined;\n this.connected = false;\n this.logger.info({ dbId: this._config.id }, 'PostgreSQL disconnected');\n }\n }\n\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\n this.ensureConnected();\n\n try {\n const schemas = await this.getSchemas(options);\n const dbSchema: DatabaseSchema = {\n dbId: this._config.id,\n dbType: 'postgres',\n schemas,\n introspectedAt: new Date(),\n version: '',\n };\n\n dbSchema.version = generateSchemaVersion(dbSchema);\n return dbSchema;\n } catch (error) {\n this.handleError(error, 'introspect');\n }\n }\n\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\n const result: SchemaMetadata[] = [];\n\n // Get all schemas\n const schemasQuery = `\n SELECT schema_name\n FROM information_schema.schemata\n WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n ORDER BY schema_name\n `;\n\n const schemasResult = await this.pool!.query(schemasQuery);\n let schemaNames = schemasResult.rows.map((r) => r.schema_name);\n\n // Apply filters\n if (options?.includeSchemas && options.includeSchemas.length > 0) {\n schemaNames = schemaNames.filter((s) => options.includeSchemas!.includes(s));\n }\n if (options?.excludeSchemas && options.excludeSchemas.length > 0) {\n schemaNames = schemaNames.filter((s) => !options.excludeSchemas!.includes(s));\n }\n\n for (const schemaName of schemaNames) {\n const tables = await this.getTables(schemaName, options);\n result.push({\n name: schemaName,\n tables,\n });\n }\n\n return result;\n }\n\n private async getTables(\n schemaName: string,\n options?: IntrospectionOptions\n ): Promise<TableMetadata[]> {\n const result: TableMetadata[] = [];\n\n // Get tables and views\n let tableTypes = \"'BASE TABLE'\";\n if (options?.includeViews) {\n tableTypes += \",'VIEW'\";\n }\n\n const tablesQuery = `\n SELECT table_name, table_type\n FROM information_schema.tables\n WHERE table_schema = $1 AND table_type IN (${tableTypes})\n ORDER BY table_name\n ${options?.maxTables ? `LIMIT ${options.maxTables}` : ''}\n `;\n\n const tablesResult = await this.pool!.query(tablesQuery, [schemaName]);\n\n for (const row of tablesResult.rows) {\n const columns = await this.getColumns(schemaName, row.table_name);\n const indexes = await this.getIndexes(schemaName, row.table_name);\n const foreignKeys = await this.getForeignKeys(schemaName, row.table_name);\n\n const primaryKey = indexes.find((idx) => idx.isPrimary);\n\n result.push({\n schema: schemaName,\n name: row.table_name,\n type: row.table_type === 'VIEW' ? 'view' : 'table',\n columns,\n primaryKey,\n indexes: indexes.filter((idx) => !idx.isPrimary),\n foreignKeys,\n });\n }\n\n return result;\n }\n\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\n const query = `\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n is_identity\n FROM information_schema.columns\n WHERE table_schema = $1 AND table_name = $2\n ORDER BY ordinal_position\n `;\n\n const result = await this.pool!.query(query, [schemaName, tableName]);\n\n return result.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n nullable: row.is_nullable === 'YES',\n defaultValue: row.column_default,\n maxLength: row.character_maximum_length,\n precision: row.numeric_precision,\n scale: row.numeric_scale,\n isAutoIncrement: row.is_identity === 'YES',\n }));\n }\n\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\n const query = `\n SELECT\n i.relname AS index_name,\n ix.indisunique AS is_unique,\n ix.indisprimary AS is_primary,\n array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) AS column_names\n FROM pg_class t\n JOIN pg_index ix ON t.oid = ix.indrelid\n JOIN pg_class i ON i.oid = ix.indexrelid\n JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n JOIN pg_namespace n ON n.oid = t.relnamespace\n WHERE n.nspname = $1 AND t.relname = $2\n GROUP BY i.relname, ix.indisunique, ix.indisprimary\n `;\n\n const result = await this.pool!.query(query, [schemaName, tableName]);\n\n return result.rows.map((row) => ({\n name: row.index_name,\n columns: row.column_names,\n isUnique: row.is_unique,\n isPrimary: row.is_primary,\n }));\n }\n\n private async getForeignKeys(\n schemaName: string,\n tableName: string\n ): Promise<ForeignKeyMetadata[]> {\n const query = `\n SELECT\n tc.constraint_name,\n array_agg(kcu.column_name ORDER BY kcu.ordinal_position) AS column_names,\n ccu.table_schema AS referenced_schema,\n ccu.table_name AS referenced_table,\n array_agg(ccu.column_name ORDER BY kcu.ordinal_position) AS referenced_columns,\n rc.update_rule,\n rc.delete_rule\n FROM information_schema.table_constraints AS tc\n JOIN information_schema.key_column_usage AS kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage AS ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n JOIN information_schema.referential_constraints AS rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_schema = $1\n AND tc.table_name = $2\n GROUP BY tc.constraint_name, ccu.table_schema, ccu.table_name, rc.update_rule, rc.delete_rule\n `;\n\n const result = await this.pool!.query(query, [schemaName, tableName]);\n\n return result.rows.map((row) => ({\n name: row.constraint_name,\n columns: row.column_names,\n referencedSchema: row.referenced_schema,\n referencedTable: row.referenced_table,\n referencedColumns: row.referenced_columns,\n onUpdate: row.update_rule,\n onDelete: row.delete_rule,\n }));\n }\n\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\n this.ensureConnected();\n\n const startTime = Date.now();\n try {\n const queryConfig: any = {\n text: sql,\n values: params,\n };\n\n if (timeoutMs) {\n queryConfig.statement_timeout = timeoutMs;\n }\n\n const result = await this.pool!.query(queryConfig);\n const executionTimeMs = Date.now() - startTime;\n\n return {\n rows: result.rows,\n columns: result.fields.map((f: any) => f.name),\n rowCount: result.rowCount || 0,\n executionTimeMs,\n affectedRows: result.rowCount || 0,\n };\n } catch (error) {\n this.handleError(error, 'query');\n }\n }\n\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\n this.ensureConnected();\n\n try {\n const explainSql = `EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS) ${sql}`;\n const result = await this.pool!.query(explainSql, params);\n\n return {\n plan: result.rows[0]['QUERY PLAN'],\n formattedPlan: JSON.stringify(result.rows[0]['QUERY PLAN'], null, 2),\n };\n } catch (error) {\n this.handleError(error, 'explain');\n }\n }\n\n async testConnection(): Promise<boolean> {\n try {\n if (!this.pool) return false;\n const client = await this.pool.connect();\n client.release();\n return true;\n } catch {\n return false;\n }\n }\n\n async getVersion(): Promise<string> {\n this.ensureConnected();\n try {\n const result = await this.pool!.query('SELECT version()');\n return result.rows[0].version;\n } catch (error) {\n this.handleError(error, 'getVersion');\n }\n }\n}\n","import pino from 'pino';\n\nlet logger: pino.Logger;\n\nexport function initLogger(level: string = 'info', pretty: boolean = false) {\n logger = pino({\n level,\n transport: pretty\n ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n }\n : undefined,\n });\n \n return logger;\n}\n\nexport function getLogger(): pino.Logger {\n if (!logger) {\n logger = initLogger();\n }\n return logger;\n}\n","import {\n DatabaseAdapter,\n DatabaseConfig,\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n DatabaseError,\n} from '../types.js';\nimport { getLogger } from '../logger.js';\n\nexport abstract class BaseAdapter implements DatabaseAdapter {\n protected logger = getLogger();\n protected connected = false;\n\n constructor(protected _config: DatabaseConfig) {}\n\n abstract connect(): Promise<void>;\n abstract disconnect(): Promise<void>;\n abstract introspect(_options?: IntrospectionOptions): Promise<DatabaseSchema>;\n abstract query(_sql: string, _params?: any[], _timeoutMs?: number): Promise<QueryResult>;\n abstract explain(_sql: string, _params?: any[]): Promise<ExplainResult>;\n abstract testConnection(): Promise<boolean>;\n abstract getVersion(): Promise<string>;\n\n protected ensureConnected(): void {\n if (!this.connected) {\n throw new DatabaseError(\n 'Database not connected',\n 'NOT_CONNECTED',\n this._config.id\n );\n }\n }\n\n protected handleError(error: any, operation: string): never {\n this.logger.error({ error, dbId: this._config.id, operation }, 'Database operation failed');\n throw new DatabaseError(\n `${operation} failed: ${error.message}`,\n error.code || 'UNKNOWN_ERROR',\n this._config.id,\n error\n );\n }\n}\n","import mysql from 'mysql2/promise';\nimport { BaseAdapter } from './base.js';\nimport {\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n TableMetadata,\n ColumnMetadata,\n IndexMetadata,\n ForeignKeyMetadata,\n SchemaMetadata,\n} from '../types.js';\nimport { generateSchemaVersion } from '../utils.js';\n\nexport class MySQLAdapter extends BaseAdapter {\n private pool?: mysql.Pool;\n private database?: string;\n\n async connect(): Promise<void> {\n try {\n this.pool = mysql.createPool({\n uri: this._config.url,\n waitForConnections: true,\n connectionLimit: this._config.pool?.max || 10,\n queueLimit: 0,\n connectTimeout: this._config.pool?.connectionTimeoutMillis || 10000,\n });\n\n // Test connection and get database name\n const connection = await this.pool.getConnection();\n const [rows] = await connection.query('SELECT DATABASE() as db');\n this.database = (rows as any)[0].db;\n connection.release();\n\n this.connected = true;\n this.logger.info({ dbId: this._config.id }, 'MySQL connected');\n } catch (error) {\n this.handleError(error, 'connect');\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = undefined;\n this.connected = false;\n this.logger.info({ dbId: this._config.id }, 'MySQL disconnected');\n }\n }\n\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\n this.ensureConnected();\n\n try {\n const schemas = await this.getSchemas(options);\n const dbSchema: DatabaseSchema = {\n dbId: this._config.id,\n dbType: 'mysql',\n schemas,\n introspectedAt: new Date(),\n version: '',\n };\n\n dbSchema.version = generateSchemaVersion(dbSchema);\n return dbSchema;\n } catch (error) {\n this.handleError(error, 'introspect');\n }\n }\n\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\n // MySQL uses the current database as the schema\n const tables = await this.getTables(this.database!, options);\n return [\n {\n name: this.database!,\n tables,\n },\n ];\n }\n\n private async getTables(\n schemaName: string,\n options?: IntrospectionOptions\n ): Promise<TableMetadata[]> {\n const result: TableMetadata[] = [];\n\n let tableTypes = \"'BASE TABLE'\";\n if (options?.includeViews) {\n tableTypes += \",'VIEW'\";\n }\n\n const tablesQuery = `\n SELECT TABLE_NAME, TABLE_TYPE, TABLE_COMMENT\n FROM information_schema.TABLES\n WHERE TABLE_SCHEMA = ? AND TABLE_TYPE IN (${tableTypes})\n ORDER BY TABLE_NAME\n ${options?.maxTables ? `LIMIT ${options.maxTables}` : ''}\n `;\n\n const [rows] = await this.pool!.query(tablesQuery, [schemaName]);\n\n for (const row of rows as any[]) {\n const columns = await this.getColumns(schemaName, row.TABLE_NAME);\n const indexes = await this.getIndexes(schemaName, row.TABLE_NAME);\n const foreignKeys = await this.getForeignKeys(schemaName, row.TABLE_NAME);\n\n const primaryKey = indexes.find((idx) => idx.isPrimary);\n\n result.push({\n schema: schemaName,\n name: row.TABLE_NAME,\n type: row.TABLE_TYPE === 'VIEW' ? 'view' : 'table',\n columns,\n primaryKey,\n indexes: indexes.filter((idx) => !idx.isPrimary),\n foreignKeys,\n comment: row.TABLE_COMMENT,\n });\n }\n\n return result;\n }\n\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\n const query = `\n SELECT\n COLUMN_NAME,\n DATA_TYPE,\n IS_NULLABLE,\n COLUMN_DEFAULT,\n CHARACTER_MAXIMUM_LENGTH,\n NUMERIC_PRECISION,\n NUMERIC_SCALE,\n EXTRA,\n COLUMN_COMMENT\n FROM information_schema.COLUMNS\n WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\n ORDER BY ORDINAL_POSITION\n `;\n\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\n\n return (rows as any[]).map((row) => ({\n name: row.COLUMN_NAME,\n dataType: row.DATA_TYPE,\n nullable: row.IS_NULLABLE === 'YES',\n defaultValue: row.COLUMN_DEFAULT,\n maxLength: row.CHARACTER_MAXIMUM_LENGTH,\n precision: row.NUMERIC_PRECISION,\n scale: row.NUMERIC_SCALE,\n isAutoIncrement: row.EXTRA.includes('auto_increment'),\n comment: row.COLUMN_COMMENT,\n }));\n }\n\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\n const query = `\n SELECT\n INDEX_NAME,\n NON_UNIQUE,\n GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS column_names\n FROM information_schema.STATISTICS\n WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\n GROUP BY INDEX_NAME, NON_UNIQUE\n `;\n\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\n\n return (rows as any[]).map((row) => ({\n name: row.INDEX_NAME,\n columns: row.column_names.split(','),\n isUnique: row.NON_UNIQUE === 0,\n isPrimary: row.INDEX_NAME === 'PRIMARY',\n }));\n }\n\n private async getForeignKeys(\n schemaName: string,\n tableName: string\n ): Promise<ForeignKeyMetadata[]> {\n const query = `\n SELECT\n kcu.CONSTRAINT_NAME,\n GROUP_CONCAT(kcu.COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS column_names,\n kcu.REFERENCED_TABLE_SCHEMA,\n kcu.REFERENCED_TABLE_NAME,\n GROUP_CONCAT(kcu.REFERENCED_COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS referenced_columns,\n rc.UPDATE_RULE,\n rc.DELETE_RULE\n FROM information_schema.KEY_COLUMN_USAGE AS kcu\n JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc\n ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n AND kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA\n WHERE kcu.TABLE_SCHEMA = ? AND kcu.TABLE_NAME = ?\n AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n GROUP BY kcu.CONSTRAINT_NAME, kcu.REFERENCED_TABLE_SCHEMA,\n kcu.REFERENCED_TABLE_NAME, rc.UPDATE_RULE, rc.DELETE_RULE\n `;\n\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\n\n return (rows as any[]).map((row) => ({\n name: row.CONSTRAINT_NAME,\n columns: row.column_names.split(','),\n referencedSchema: row.REFERENCED_TABLE_SCHEMA,\n referencedTable: row.REFERENCED_TABLE_NAME,\n referencedColumns: row.referenced_columns.split(','),\n onUpdate: row.UPDATE_RULE,\n onDelete: row.DELETE_RULE,\n }));\n }\n\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\n this.ensureConnected();\n\n const startTime = Date.now();\n try {\n const connection = await this.pool!.getConnection();\n \n if (timeoutMs) {\n await connection.query(`SET SESSION max_execution_time=${timeoutMs}`);\n }\n\n const [rows, fields] = await connection.query(sql, params);\n connection.release();\n\n const executionTimeMs = Date.now() - startTime;\n\n return {\n rows: Array.isArray(rows) ? rows : [],\n columns: Array.isArray(fields) ? fields.map((f: any) => f.name) : [],\n rowCount: Array.isArray(rows) ? rows.length : 0,\n executionTimeMs,\n affectedRows: (rows as any).affectedRows,\n };\n } catch (error) {\n this.handleError(error, 'query');\n }\n }\n\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\n this.ensureConnected();\n\n try {\n const explainSql = `EXPLAIN FORMAT=JSON ${sql}`;\n const [rows] = await this.pool!.query(explainSql, params);\n\n return {\n plan: (rows as any)[0].EXPLAIN,\n formattedPlan: JSON.stringify((rows as any)[0].EXPLAIN, null, 2),\n };\n } catch (error) {\n this.handleError(error, 'explain');\n }\n }\n\n async testConnection(): Promise<boolean> {\n try {\n if (!this.pool) return false;\n const connection = await this.pool.getConnection();\n connection.release();\n return true;\n } catch {\n return false;\n }\n }\n\n async getVersion(): Promise<string> {\n this.ensureConnected();\n try {\n const [rows] = await this.pool!.query('SELECT VERSION() as version');\n return (rows as any)[0].version;\n } catch (error) {\n this.handleError(error, 'getVersion');\n }\n }\n}\n","import Database from 'better-sqlite3';\nimport { BaseAdapter } from './base.js';\nimport {\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n TableMetadata,\n ColumnMetadata,\n IndexMetadata,\n ForeignKeyMetadata,\n SchemaMetadata,\n} from '../types.js';\nimport { generateSchemaVersion } from '../utils.js';\n\nexport class SQLiteAdapter extends BaseAdapter {\n private db?: Database.Database;\n\n async connect(): Promise<void> {\n try {\n const dbPath = this._config.path || this._config.url;\n if (!dbPath) {\n throw new Error('SQLite requires path or url configuration');\n }\n\n this.db = new Database(dbPath, {\n readonly: this._config.readOnly,\n fileMustExist: false,\n });\n\n // Enable foreign keys\n this.db.pragma('foreign_keys = ON');\n\n this.connected = true;\n this.logger.info({ dbId: this._config.id, path: dbPath }, 'SQLite connected');\n } catch (error) {\n this.handleError(error, 'connect');\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.db) {\n this.db.close();\n this.db = undefined;\n this.connected = false;\n this.logger.info({ dbId: this._config.id }, 'SQLite disconnected');\n }\n }\n\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\n this.ensureConnected();\n\n try {\n const schemas = await this.getSchemas(options);\n const dbSchema: DatabaseSchema = {\n dbId: this._config.id,\n dbType: 'sqlite',\n schemas,\n introspectedAt: new Date(),\n version: '',\n };\n\n dbSchema.version = generateSchemaVersion(dbSchema);\n return dbSchema;\n } catch (error) {\n this.handleError(error, 'introspect');\n }\n }\n\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\n const tables = await this.getTables('main', options);\n return [\n {\n name: 'main',\n tables,\n },\n ];\n }\n\n private async getTables(\n schemaName: string,\n options?: IntrospectionOptions\n ): Promise<TableMetadata[]> {\n const result: TableMetadata[] = [];\n\n let query = `\n SELECT name, type\n FROM sqlite_master\n WHERE type IN ('table', 'view')\n AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `;\n\n if (options?.maxTables) {\n query += ` LIMIT ${options.maxTables}`;\n }\n\n const tables = this.db!.prepare(query).all() as Array<{ name: string; type: string }>;\n\n for (const table of tables) {\n if (table.type === 'view' && !options?.includeViews) {\n continue;\n }\n\n const columns = await this.getColumns(table.name);\n const indexes = await this.getIndexes(table.name);\n const foreignKeys = await this.getForeignKeys(table.name);\n\n const primaryKey = indexes.find((idx) => idx.isPrimary);\n\n result.push({\n schema: schemaName,\n name: table.name,\n type: table.type === 'view' ? 'view' : 'table',\n columns,\n primaryKey,\n indexes: indexes.filter((idx) => !idx.isPrimary),\n foreignKeys,\n });\n }\n\n return result;\n }\n\n private async getColumns(tableName: string): Promise<ColumnMetadata[]> {\n const pragma = this.db!.prepare(`PRAGMA table_info(${tableName})`).all() as Array<{\n cid: number;\n name: string;\n type: string;\n notnull: number;\n dflt_value: string | null;\n pk: number;\n }>;\n\n return pragma.map((col) => ({\n name: col.name,\n dataType: col.type || 'TEXT',\n nullable: col.notnull === 0,\n defaultValue: col.dflt_value || undefined,\n isAutoIncrement: col.pk === 1 && col.type.toUpperCase() === 'INTEGER',\n }));\n }\n\n private async getIndexes(tableName: string): Promise<IndexMetadata[]> {\n const result: IndexMetadata[] = [];\n\n // Get all indexes\n const indexes = this.db!.prepare(`PRAGMA index_list(${tableName})`).all() as Array<{\n name: string;\n unique: number;\n origin: string;\n }>;\n\n for (const index of indexes) {\n const indexInfo = this.db!.prepare(`PRAGMA index_info(${index.name})`).all() as Array<{\n seqno: number;\n cid: number;\n name: string;\n }>;\n\n result.push({\n name: index.name,\n columns: indexInfo.map((info) => info.name),\n isUnique: index.unique === 1,\n isPrimary: index.origin === 'pk',\n });\n }\n\n return result;\n }\n\n private async getForeignKeys(tableName: string): Promise<ForeignKeyMetadata[]> {\n const foreignKeys = this.db!.prepare(`PRAGMA foreign_key_list(${tableName})`).all() as Array<{\n id: number;\n seq: number;\n table: string;\n from: string;\n to: string;\n on_update: string;\n on_delete: string;\n }>;\n\n // Group by FK id\n const grouped = new Map<number, typeof foreignKeys>();\n for (const fk of foreignKeys) {\n if (!grouped.has(fk.id)) {\n grouped.set(fk.id, []);\n }\n grouped.get(fk.id)!.push(fk);\n }\n\n return Array.from(grouped.values()).map((fks) => ({\n name: `fk_${tableName}_${fks[0].id}`,\n columns: fks.map((fk) => fk.from),\n referencedSchema: 'main',\n referencedTable: fks[0].table,\n referencedColumns: fks.map((fk) => fk.to),\n onUpdate: fks[0].on_update,\n onDelete: fks[0].on_delete,\n }));\n }\n\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\n this.ensureConnected();\n\n const startTime = Date.now();\n try {\n if (timeoutMs) {\n this.db!.pragma(`busy_timeout = ${timeoutMs}`);\n }\n\n const stmt = this.db!.prepare(sql);\n const isSelect = sql.trim().toUpperCase().startsWith('SELECT');\n\n let rows: any[];\n let affectedRows = 0;\n\n if (isSelect) {\n rows = stmt.all(...params);\n } else {\n const result = stmt.run(...params);\n rows = [];\n affectedRows = result.changes;\n }\n\n const executionTimeMs = Date.now() - startTime;\n const columns = rows.length > 0 ? Object.keys(rows[0]) : [];\n\n return {\n rows,\n columns,\n rowCount: rows.length,\n executionTimeMs,\n affectedRows,\n };\n } catch (error) {\n this.handleError(error, 'query');\n }\n }\n\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\n this.ensureConnected();\n\n try {\n const explainSql = `EXPLAIN QUERY PLAN ${sql}`;\n const stmt = this.db!.prepare(explainSql);\n const plan = stmt.all(...params);\n\n return {\n plan,\n formattedPlan: JSON.stringify(plan, null, 2),\n };\n } catch (error) {\n this.handleError(error, 'explain');\n }\n }\n\n async testConnection(): Promise<boolean> {\n try {\n if (!this.db) return false;\n this.db.prepare('SELECT 1').get();\n return true;\n } catch {\n return false;\n }\n }\n\n async getVersion(): Promise<string> {\n this.ensureConnected();\n try {\n const result = this.db!.prepare('SELECT sqlite_version() as version').get() as {\n version: string;\n };\n return `SQLite ${result.version}`;\n } catch (error) {\n this.handleError(error, 'getVersion');\n }\n }\n}\n","import { Connection, Request } from 'tedious';\nimport { BaseAdapter } from './base.js';\nimport {\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n TableMetadata,\n ColumnMetadata,\n IndexMetadata,\n ForeignKeyMetadata,\n SchemaMetadata,\n} from '../types.js';\nimport { generateSchemaVersion } from '../utils.js';\n\nexport class MSSQLAdapter extends BaseAdapter {\n private connection?: Connection;\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n // Parse connection string\n const config = this.parseConnectionString(this._config.url!);\n\n this.connection = new Connection(config);\n\n this.connection.on('connect', (err) => {\n if (err) {\n reject(err);\n } else {\n this.connected = true;\n this.logger.info({ dbId: this._config.id }, 'SQL Server connected');\n resolve();\n }\n });\n\n this.connection.connect();\n } catch (error) {\n this.handleError(error, 'connect');\n }\n });\n }\n\n private parseConnectionString(connStr: string): any {\n const config: any = {\n options: {\n encrypt: true,\n trustServerCertificate: true,\n enableArithAbort: true,\n },\n };\n\n // Simple parser for SQL Server connection strings\n const parts = connStr.split(';').filter((p) => p.trim());\n for (const part of parts) {\n const [key, value] = part.split('=').map((s) => s.trim());\n const lowerKey = key.toLowerCase();\n\n if (lowerKey === 'server') {\n const [host, port] = value.split(',');\n config.server = host;\n if (port) config.options.port = parseInt(port);\n } else if (lowerKey === 'database') {\n config.options.database = value;\n } else if (lowerKey === 'user id') {\n config.authentication = {\n type: 'default',\n options: { userName: value, password: '' },\n };\n } else if (lowerKey === 'password') {\n if (config.authentication) {\n config.authentication.options.password = value;\n }\n } else if (lowerKey === 'encrypt') {\n config.options.encrypt = value.toLowerCase() === 'true';\n } else if (lowerKey === 'trustservercertificate') {\n config.options.trustServerCertificate = value.toLowerCase() === 'true';\n }\n }\n\n return config;\n }\n\n async disconnect(): Promise<void> {\n if (this.connection) {\n this.connection.close();\n this.connection = undefined;\n this.connected = false;\n this.logger.info({ dbId: this._config.id }, 'SQL Server disconnected');\n }\n }\n\n private executeQuery(sql: string, _params: any[] = []): Promise<any[]> {\n return new Promise((resolve, reject) => {\n const rows: any[] = [];\n const request = new Request(sql, (err) => {\n if (err) {\n reject(err);\n } else {\n resolve(rows);\n }\n });\n\n request.on('row', (columns) => {\n const row: any = {};\n columns.forEach((col: any) => {\n row[col.metadata.colName] = col.value;\n });\n rows.push(row);\n });\n\n this.connection!.execSql(request);\n });\n }\n\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\n this.ensureConnected();\n\n try {\n const schemas = await this.getSchemas(options);\n const dbSchema: DatabaseSchema = {\n dbId: this._config.id,\n dbType: 'mssql',\n schemas,\n introspectedAt: new Date(),\n version: '',\n };\n\n dbSchema.version = generateSchemaVersion(dbSchema);\n return dbSchema;\n } catch (error) {\n this.handleError(error, 'introspect');\n }\n }\n\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\n const result: SchemaMetadata[] = [];\n\n const schemasQuery = `\n SELECT SCHEMA_NAME\n FROM INFORMATION_SCHEMA.SCHEMATA\n WHERE SCHEMA_NAME NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n ORDER BY SCHEMA_NAME\n `;\n\n const schemasResult = await this.executeQuery(schemasQuery);\n let schemaNames = schemasResult.map((r) => r.SCHEMA_NAME);\n\n if (options?.includeSchemas && options.includeSchemas.length > 0) {\n schemaNames = schemaNames.filter((s) => options.includeSchemas!.includes(s));\n }\n if (options?.excludeSchemas && options.excludeSchemas.length > 0) {\n schemaNames = schemaNames.filter((s) => !options.excludeSchemas!.includes(s));\n }\n\n for (const schemaName of schemaNames) {\n const tables = await this.getTables(schemaName, options);\n result.push({\n name: schemaName,\n tables,\n });\n }\n\n return result;\n }\n\n private async getTables(\n schemaName: string,\n options?: IntrospectionOptions\n ): Promise<TableMetadata[]> {\n const result: TableMetadata[] = [];\n\n let tableTypes = \"'BASE TABLE'\";\n if (options?.includeViews) {\n tableTypes += \",'VIEW'\";\n }\n\n const tablesQuery = `\n SELECT TABLE_NAME, TABLE_TYPE\n FROM INFORMATION_SCHEMA.TABLES\n WHERE TABLE_SCHEMA = '${schemaName}' AND TABLE_TYPE IN (${tableTypes})\n ORDER BY TABLE_NAME\n ${options?.maxTables ? `OFFSET 0 ROWS FETCH NEXT ${options.maxTables} ROWS ONLY` : ''}\n `;\n\n const tablesResult = await this.executeQuery(tablesQuery);\n\n for (const row of tablesResult) {\n const columns = await this.getColumns(schemaName, row.TABLE_NAME);\n const indexes = await this.getIndexes(schemaName, row.TABLE_NAME);\n const foreignKeys = await this.getForeignKeys(schemaName, row.TABLE_NAME);\n\n const primaryKey = indexes.find((idx) => idx.isPrimary);\n\n result.push({\n schema: schemaName,\n name: row.TABLE_NAME,\n type: row.TABLE_TYPE === 'VIEW' ? 'view' : 'table',\n columns,\n primaryKey,\n indexes: indexes.filter((idx) => !idx.isPrimary),\n foreignKeys,\n });\n }\n\n return result;\n }\n\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\n const query = `\n SELECT\n COLUMN_NAME,\n DATA_TYPE,\n IS_NULLABLE,\n COLUMN_DEFAULT,\n CHARACTER_MAXIMUM_LENGTH,\n NUMERIC_PRECISION,\n NUMERIC_SCALE,\n COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'IsIdentity') AS IS_IDENTITY\n FROM INFORMATION_SCHEMA.COLUMNS\n WHERE TABLE_SCHEMA = '${schemaName}' AND TABLE_NAME = '${tableName}'\n ORDER BY ORDINAL_POSITION\n `;\n\n const result = await this.executeQuery(query);\n\n return result.map((row) => ({\n name: row.COLUMN_NAME,\n dataType: row.DATA_TYPE,\n nullable: row.IS_NULLABLE === 'YES',\n defaultValue: row.COLUMN_DEFAULT,\n maxLength: row.CHARACTER_MAXIMUM_LENGTH,\n precision: row.NUMERIC_PRECISION,\n scale: row.NUMERIC_SCALE,\n isAutoIncrement: row.IS_IDENTITY === 1,\n }));\n }\n\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\n const query = `\n SELECT\n i.name AS index_name,\n i.is_unique,\n i.is_primary_key,\n STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY ic.key_ordinal) AS column_names\n FROM sys.indexes i\n INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\n INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\n INNER JOIN sys.tables t ON i.object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name = '${schemaName}' AND t.name = '${tableName}'\n GROUP BY i.name, i.is_unique, i.is_primary_key\n `;\n\n const result = await this.executeQuery(query);\n\n return result.map((row) => ({\n name: row.index_name,\n columns: row.column_names.split(','),\n isUnique: row.is_unique,\n isPrimary: row.is_primary_key,\n }));\n }\n\n private async getForeignKeys(\n schemaName: string,\n tableName: string\n ): Promise<ForeignKeyMetadata[]> {\n const query = `\n SELECT\n fk.name AS constraint_name,\n STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY fkc.constraint_column_id) AS column_names,\n rs.name AS referenced_schema,\n rt.name AS referenced_table,\n STRING_AGG(rc.name, ',') WITHIN GROUP (ORDER BY fkc.constraint_column_id) AS referenced_columns,\n fk.update_referential_action_desc,\n fk.delete_referential_action_desc\n FROM sys.foreign_keys fk\n INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\n INNER JOIN sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id\n INNER JOIN sys.columns rc ON fkc.referenced_object_id = rc.object_id AND fkc.referenced_column_id = rc.column_id\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n INNER JOIN sys.tables rt ON fk.referenced_object_id = rt.object_id\n INNER JOIN sys.schemas rs ON rt.schema_id = rs.schema_id\n WHERE s.name = '${schemaName}' AND t.name = '${tableName}'\n GROUP BY fk.name, rs.name, rt.name, fk.update_referential_action_desc, fk.delete_referential_action_desc\n `;\n\n const result = await this.executeQuery(query);\n\n return result.map((row) => ({\n name: row.constraint_name,\n columns: row.column_names.split(','),\n referencedSchema: row.referenced_schema,\n referencedTable: row.referenced_table,\n referencedColumns: row.referenced_columns.split(','),\n onUpdate: row.update_referential_action_desc,\n onDelete: row.delete_referential_action_desc,\n }));\n }\n\n async query(sql: string, params: any[] = [], _timeoutMs?: number): Promise<QueryResult> {\n this.ensureConnected();\n\n const startTime = Date.now();\n try {\n const rows = await this.executeQuery(sql, params);\n const executionTimeMs = Date.now() - startTime;\n const columns = rows.length > 0 ? Object.keys(rows[0]) : [];\n\n return {\n rows,\n columns,\n rowCount: rows.length,\n executionTimeMs,\n };\n } catch (error) {\n this.handleError(error, 'query');\n }\n }\n\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\n this.ensureConnected();\n\n try {\n const explainSql = `SET SHOWPLAN_TEXT ON; ${sql}; SET SHOWPLAN_TEXT OFF;`;\n const plan = await this.executeQuery(explainSql, params);\n\n return {\n plan,\n formattedPlan: JSON.stringify(plan, null, 2),\n };\n } catch (error) {\n this.handleError(error, 'explain');\n }\n }\n\n async testConnection(): Promise<boolean> {\n try {\n if (!this.connection) return false;\n await this.executeQuery('SELECT 1');\n return true;\n } catch {\n return false;\n }\n }\n\n async getVersion(): Promise<string> {\n this.ensureConnected();\n try {\n const result = await this.executeQuery('SELECT @@VERSION as version');\n return result[0].version;\n } catch (error) {\n this.handleError(error, 'getVersion');\n }\n }\n}\n","import { BaseAdapter } from './base.js';\nimport {\n DatabaseSchema,\n QueryResult,\n ExplainResult,\n IntrospectionOptions,\n} from '../types.js';\n\n/**\n * Oracle adapter stub - requires Oracle Instant Client to be installed\n * TODO: Implement full Oracle support when environment supports it\n * \n * To use Oracle:\n * 1. Install Oracle Instant Client\n * 2. Set LD_LIBRARY_PATH (Linux) or PATH (Windows) to include Instant Client\n * 3. Install oracledb package: npm install oracledb\n * 4. Implement the methods below using oracledb\n */\nexport class OracleAdapter extends BaseAdapter {\n private connection?: any;\n\n async connect(): Promise<void> {\n this.logger.warn(\n { dbId: this._config.id },\n 'Oracle adapter is not fully implemented. Requires Oracle Instant Client and oracledb package.'\n );\n \n // TODO: Implement Oracle connection\n // Example:\n // const oracledb = require('oracledb');\n // this.connection = await oracledb.getConnection({\n // user: config.user,\n // password: config.password,\n // connectString: config.connectString,\n // poolMin: this._config.pool?.min || 2,\n // poolMax: this._config.pool?.max || 10,\n // });\n \n throw new Error(\n 'Oracle adapter not implemented. Please install Oracle Instant Client and implement OracleAdapter methods.'\n );\n }\n\n async disconnect(): Promise<void> {\n // TODO: Implement Oracle disconnect\n if (this.connection) {\n // await this.connection.close();\n this.connection = undefined;\n this.connected = false;\n }\n }\n\n async introspect(_options?: IntrospectionOptions): Promise<DatabaseSchema> {\n this.ensureConnected();\n\n // TODO: Implement Oracle introspection\n // Query ALL_TABLES, ALL_TAB_COLUMNS, ALL_CONSTRAINTS, etc.\n throw new Error('Oracle introspection not implemented');\n }\n\n async query(_sql: string, _params: any[] = [], _timeoutMs?: number): Promise<QueryResult> {\n this.ensureConnected();\n\n // TODO: Implement Oracle query execution\n throw new Error('Oracle query not implemented');\n }\n\n async explain(_sql: string, _params: any[] = []): Promise<ExplainResult> {\n this.ensureConnected();\n\n // TODO: Implement Oracle EXPLAIN PLAN\n // Use: EXPLAIN PLAN FOR ... then SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)\n throw new Error('Oracle explain not implemented');\n }\n\n async testConnection(): Promise<boolean> {\n // TODO: Implement connection test\n return false;\n }\n\n async getVersion(): Promise<string> {\n // TODO: Query v$version or SELECT * FROM v$version\n return 'Oracle (not implemented)';\n }\n}\n","import { DatabaseAdapter, DatabaseConfig } from '../types.js';\nimport { PostgresAdapter } from './postgres.js';\nimport { MySQLAdapter } from './mysql.js';\nimport { SQLiteAdapter } from './sqlite.js';\nimport { MSSQLAdapter } from './mssql.js';\nimport { OracleAdapter } from './oracle.js';\n\nexport function createAdapter(config: DatabaseConfig): DatabaseAdapter {\n switch (config.type) {\n case 'postgres':\n return new PostgresAdapter(config);\n case 'mysql':\n return new MySQLAdapter(config);\n case 'sqlite':\n return new SQLiteAdapter(config);\n case 'mssql':\n return new MSSQLAdapter(config);\n case 'oracle':\n return new OracleAdapter(config);\n default:\n throw new Error(`Unsupported database type: ${config.type}`);\n }\n}\n\nexport { PostgresAdapter, MySQLAdapter, SQLiteAdapter, MSSQLAdapter, OracleAdapter };\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { DatabaseSchema, Relationship, CacheError } from './types.js';\nimport { inferRelationships } from './utils.js';\nimport { getLogger } from './logger.js';\n\nexport interface CacheEntry {\n schema: DatabaseSchema;\n relationships: Relationship[];\n cachedAt: Date;\n ttlMinutes: number;\n}\n\nexport interface CacheStatus {\n dbId: string;\n exists: boolean;\n age?: number; // milliseconds\n ttlMinutes?: number;\n expired?: boolean;\n version?: string;\n tableCount?: number;\n relationshipCount?: number;\n}\n\nexport class SchemaCache {\n private logger = getLogger();\n private cache = new Map<string, CacheEntry>();\n private introspectionLocks = new Map<string, Promise<void>>();\n\n constructor(\n private _cacheDir: string,\n private _defaultTtlMinutes: number\n ) {}\n\n async init(): Promise<void> {\n try {\n await fs.mkdir(this._cacheDir, { recursive: true });\n this.logger.info({ cacheDir: this._cacheDir }, 'Schema cache initialized');\n } catch (error: any) {\n throw new CacheError('Failed to initialize cache directory', error);\n }\n }\n\n /**\n * Get cached schema if valid, otherwise return null\n */\n async get(dbId: string): Promise<CacheEntry | null> {\n // Check memory cache first\n const memEntry = this.cache.get(dbId);\n if (memEntry && !this.isExpired(memEntry)) {\n return memEntry;\n }\n\n // Try to load from disk\n try {\n const diskEntry = await this.loadFromDisk(dbId);\n if (diskEntry && !this.isExpired(diskEntry)) {\n this.cache.set(dbId, diskEntry);\n return diskEntry;\n }\n } catch (error) {\n this.logger.warn({ dbId, error }, 'Failed to load cache from disk');\n }\n\n return null;\n }\n\n /**\n * Set or update cache entry\n */\n async set(dbId: string, schema: DatabaseSchema, ttlMinutes?: number): Promise<void> {\n const entry: CacheEntry = {\n schema,\n relationships: this.buildRelationships(schema),\n cachedAt: new Date(),\n ttlMinutes: ttlMinutes || this._defaultTtlMinutes,\n };\n\n this.cache.set(dbId, entry);\n\n // Persist to disk asynchronously\n this.saveToDisk(dbId, entry).catch((error) => {\n this.logger.error({ dbId, error }, 'Failed to save cache to disk');\n });\n }\n\n /**\n * Clear cache for a specific database or all databases\n */\n async clear(dbId?: string): Promise<void> {\n if (dbId) {\n this.cache.delete(dbId);\n try {\n const filePath = this.getCacheFilePath(dbId);\n await fs.unlink(filePath);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n this.logger.warn({ dbId, error }, 'Failed to delete cache file');\n }\n }\n this.logger.info({ dbId }, 'Cache cleared');\n } else {\n this.cache.clear();\n try {\n const files = await fs.readdir(this._cacheDir);\n await Promise.all(\n files\n .filter((f) => f.endsWith('.json'))\n .map((f) => fs.unlink(path.join(this._cacheDir, f)))\n );\n } catch (error) {\n this.logger.warn({ error }, 'Failed to clear cache directory');\n }\n this.logger.info('All caches cleared');\n }\n }\n\n /**\n * Get cache status\n */\n async getStatus(dbId?: string): Promise<CacheStatus[]> {\n const statuses: CacheStatus[] = [];\n\n if (dbId) {\n const status = await this.getStatusForDb(dbId);\n statuses.push(status);\n } else {\n // Get status for all cached databases\n const dbIds = new Set([\n ...this.cache.keys(),\n ...(await this.getPersistedDbIds()),\n ]);\n\n for (const id of dbIds) {\n const status = await this.getStatusForDb(id);\n statuses.push(status);\n }\n }\n\n return statuses;\n }\n\n private async getStatusForDb(dbId: string): Promise<CacheStatus> {\n const entry = await this.get(dbId);\n\n if (!entry) {\n return {\n dbId,\n exists: false,\n };\n }\n\n const age = Date.now() - new Date(entry.cachedAt).getTime();\n const expired = this.isExpired(entry);\n\n return {\n dbId,\n exists: true,\n age,\n ttlMinutes: entry.ttlMinutes,\n expired,\n version: entry.schema.version,\n tableCount: entry.schema.schemas.reduce((sum, s) => sum + s.tables.length, 0),\n relationshipCount: entry.relationships.length,\n };\n }\n\n /**\n * Acquire lock for introspection to prevent concurrent introspection\n */\n async acquireIntrospectionLock(dbId: string): Promise<() => void> {\n // Wait for existing introspection to complete\n const existingLock = this.introspectionLocks.get(dbId);\n if (existingLock) {\n await existingLock;\n }\n\n // Create new lock\n let releaseLock: () => void;\n const lockPromise = new Promise<void>((resolve) => {\n releaseLock = resolve;\n });\n\n this.introspectionLocks.set(dbId, lockPromise);\n\n return () => {\n releaseLock!();\n this.introspectionLocks.delete(dbId);\n };\n }\n\n private isExpired(entry: CacheEntry): boolean {\n const age = Date.now() - new Date(entry.cachedAt).getTime();\n const ttlMs = entry.ttlMinutes * 60 * 1000;\n return age > ttlMs;\n }\n\n private buildRelationships(schema: DatabaseSchema): Relationship[] {\n const relationships: Relationship[] = [];\n\n // Collect explicit foreign key relationships\n for (const schemaObj of schema.schemas) {\n for (const table of schemaObj.tables) {\n for (const fk of table.foreignKeys) {\n relationships.push({\n fromSchema: schemaObj.name,\n fromTable: table.name,\n fromColumns: fk.columns,\n toSchema: fk.referencedSchema,\n toTable: fk.referencedTable,\n toColumns: fk.referencedColumns,\n type: 'foreign_key',\n });\n }\n }\n }\n\n // Infer additional relationships\n const inferred = inferRelationships(schema);\n \n // Avoid duplicates\n const relationshipKeys = new Set(\n relationships.map((r) => this.getRelationshipKey(r))\n );\n \n for (const rel of inferred) {\n const key = this.getRelationshipKey(rel);\n if (!relationshipKeys.has(key)) {\n relationships.push(rel);\n relationshipKeys.add(key);\n }\n }\n\n return relationships;\n }\n\n private getRelationshipKey(rel: Relationship): string {\n return `${rel.fromSchema}.${rel.fromTable}.${rel.fromColumns.join(',')}→${rel.toSchema}.${rel.toTable}.${rel.toColumns.join(',')}`;\n }\n\n private getCacheFilePath(dbId: string): string {\n return path.join(this._cacheDir, `${dbId}.json`);\n }\n\n private async loadFromDisk(dbId: string): Promise<CacheEntry | null> {\n try {\n const filePath = this.getCacheFilePath(dbId);\n const data = await fs.readFile(filePath, 'utf-8');\n const entry = JSON.parse(data);\n \n // Convert date strings back to Date objects\n entry.cachedAt = new Date(entry.cachedAt);\n entry.schema.introspectedAt = new Date(entry.schema.introspectedAt);\n \n return entry;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n }\n\n private async saveToDisk(dbId: string, entry: CacheEntry): Promise<void> {\n const filePath = this.getCacheFilePath(dbId);\n const data = JSON.stringify(entry, null, 2);\n await fs.writeFile(filePath, data, 'utf-8');\n }\n\n private async getPersistedDbIds(): Promise<string[]> {\n try {\n const files = await fs.readdir(this._cacheDir);\n return files\n .filter((f) => f.endsWith('.json'))\n .map((f) => f.replace('.json', ''));\n } catch {\n return [];\n }\n }\n}\n","import { QueryHistoryEntry } from './types.js';\nimport { extractTableNames } from './utils.js';\n\nexport class QueryTracker {\n private history = new Map<string, QueryHistoryEntry[]>();\n private maxHistoryPerDb = 100;\n\n track(\n dbId: string,\n sql: string,\n executionTimeMs: number,\n rowCount: number,\n error?: string\n ): void {\n const entry: QueryHistoryEntry = {\n timestamp: new Date(),\n sql,\n tables: extractTableNames(sql),\n executionTimeMs,\n rowCount,\n error,\n };\n\n if (!this.history.has(dbId)) {\n this.history.set(dbId, []);\n }\n\n const dbHistory = this.history.get(dbId)!;\n dbHistory.push(entry);\n\n // Keep only recent queries\n if (dbHistory.length > this.maxHistoryPerDb) {\n dbHistory.shift();\n }\n }\n\n getHistory(dbId: string, limit?: number): QueryHistoryEntry[] {\n const dbHistory = this.history.get(dbId) || [];\n if (limit) {\n return dbHistory.slice(-limit);\n }\n return [...dbHistory];\n }\n\n getStats(dbId: string): {\n totalQueries: number;\n avgExecutionTime: number;\n errorCount: number;\n tableUsage: Record<string, number>;\n } {\n const dbHistory = this.history.get(dbId) || [];\n\n const stats = {\n totalQueries: dbHistory.length,\n avgExecutionTime: 0,\n errorCount: 0,\n tableUsage: {} as Record<string, number>,\n };\n\n if (dbHistory.length === 0) {\n return stats;\n }\n\n let totalTime = 0;\n for (const entry of dbHistory) {\n totalTime += entry.executionTimeMs;\n if (entry.error) {\n stats.errorCount++;\n }\n\n for (const table of entry.tables) {\n stats.tableUsage[table] = (stats.tableUsage[table] || 0) + 1;\n }\n }\n\n stats.avgExecutionTime = totalTime / dbHistory.length;\n\n return stats;\n }\n\n clear(dbId?: string): void {\n if (dbId) {\n this.history.delete(dbId);\n } else {\n this.history.clear();\n }\n }\n}\n","import { DatabaseAdapter, DatabaseConfig, IntrospectionOptions, QueryResult } from './types.js';\nimport { createAdapter } from './adapters/index.js';\nimport { SchemaCache, CacheEntry } from './cache.js';\nimport { QueryTracker } from './query-tracker.js';\nimport { isWriteOperation, findJoinPaths } from './utils.js';\nimport { getLogger } from './logger.js';\n\nexport interface DatabaseManagerOptions {\n cacheDir: string;\n cacheTtlMinutes: number;\n allowWrite: boolean;\n allowedWriteOperations?: string[];\n disableDangerousOperations: boolean;\n}\n\nexport class DatabaseManager {\n private logger = getLogger();\n private adapters = new Map<string, DatabaseAdapter>();\n private cache: SchemaCache;\n private queryTracker = new QueryTracker();\n\n constructor(\n private _configs: DatabaseConfig[],\n private options: DatabaseManagerOptions\n ) {\n this.cache = new SchemaCache(options.cacheDir, options.cacheTtlMinutes);\n }\n\n async init(): Promise<void> {\n await this.cache.init();\n\n // Create adapters\n for (const config of this._configs) {\n const adapter = createAdapter(config);\n this.adapters.set(config.id, adapter);\n\n // Connect eagerly if configured\n if (config.eagerConnect) {\n try {\n await this.connect(config.id);\n } catch (error) {\n this.logger.error({ dbId: config.id, error }, 'Failed to eager connect');\n }\n }\n }\n\n this.logger.info({ databases: this._configs.length }, 'Database manager initialized');\n }\n\n async shutdown(): Promise<void> {\n for (const [dbId, adapter] of this.adapters) {\n try {\n await adapter.disconnect();\n } catch (error) {\n this.logger.error({ dbId, error }, 'Failed to disconnect');\n }\n }\n this.logger.info('Database manager shut down');\n }\n\n getConfigs(): DatabaseConfig[] {\n return this._configs;\n }\n\n getConfig(dbId: string): DatabaseConfig | undefined {\n return this._configs.find((c) => c.id === dbId);\n }\n\n private getAdapter(dbId: string): DatabaseAdapter {\n const adapter = this.adapters.get(dbId);\n if (!adapter) {\n throw new Error(`Database not found: ${dbId}`);\n }\n return adapter;\n }\n\n private async connect(dbId: string): Promise<void> {\n const adapter = this.getAdapter(dbId);\n await adapter.connect();\n }\n\n private async ensureConnected(dbId: string): Promise<void> {\n const adapter = this.getAdapter(dbId);\n const connected = await adapter.testConnection();\n if (!connected) {\n await this.connect(dbId);\n }\n }\n\n async testConnection(dbId: string): Promise<boolean> {\n const adapter = this.getAdapter(dbId);\n return adapter.testConnection();\n }\n\n async getVersion(dbId: string): Promise<string> {\n await this.ensureConnected(dbId);\n const adapter = this.getAdapter(dbId);\n return adapter.getVersion();\n }\n\n async introspectSchema(\n dbId: string,\n forceRefresh: boolean = false,\n options?: IntrospectionOptions\n ): Promise<CacheEntry> {\n // Check cache first\n if (!forceRefresh) {\n const cached = await this.cache.get(dbId);\n if (cached) {\n this.logger.debug({ dbId }, 'Using cached schema');\n return cached;\n }\n }\n\n // Acquire lock to prevent concurrent introspection\n const releaseLock = await this.cache.acquireIntrospectionLock(dbId);\n\n try {\n // Double-check cache after acquiring lock\n if (!forceRefresh) {\n const cached = await this.cache.get(dbId);\n if (cached) {\n return cached;\n }\n }\n\n this.logger.info({ dbId, forceRefresh }, 'Introspecting schema');\n\n await this.ensureConnected(dbId);\n const adapter = this.getAdapter(dbId);\n const schema = await adapter.introspect(options);\n\n // Cache the result\n const config = this.getConfig(dbId);\n await this.cache.set(dbId, schema, config?.introspection?.maxTables);\n\n const entry = await this.cache.get(dbId);\n return entry!;\n } finally {\n releaseLock();\n }\n }\n\n async getSchema(dbId: string): Promise<CacheEntry> {\n // Ensure schema is cached\n return this.introspectSchema(dbId, false);\n }\n\n async runQuery(\n dbId: string,\n sql: string,\n params: any[] = [],\n timeoutMs?: number\n ): Promise<QueryResult> {\n const config = this.getConfig(dbId);\n \n // Check if write operation\n if (isWriteOperation(sql)) {\n if (!this.options.allowWrite && !config?.readOnly === false) {\n throw new Error('Write operations are not allowed. Set allowWrite in config.');\n }\n\n // Check for dangerous operations (DELETE, TRUNCATE, DROP)\n if (this.options.disableDangerousOperations) {\n const operation = sql.trim().split(/\\s+/)[0].toUpperCase();\n const dangerousOps = ['DELETE', 'TRUNCATE', 'DROP'];\n if (dangerousOps.includes(operation)) {\n throw new Error(`Dangerous operation ${operation} is disabled. Set disableDangerousOperations: false in security config to allow.`);\n }\n }\n\n // Check allowed operations\n if (this.options.allowedWriteOperations && this.options.allowedWriteOperations.length > 0) {\n const operation = sql.trim().split(/\\s+/)[0].toUpperCase();\n if (!this.options.allowedWriteOperations.includes(operation)) {\n throw new Error(`Write operation ${operation} is not allowed.`);\n }\n }\n }\n\n // Ensure schema is cached (for relationship annotation)\n await this.introspectSchema(dbId, false);\n\n await this.ensureConnected(dbId);\n const adapter = this.getAdapter(dbId);\n\n try {\n const result = await adapter.query(sql, params, timeoutMs);\n \n // Track query\n this.queryTracker.track(dbId, sql, result.executionTimeMs, result.rowCount);\n\n return result;\n } catch (error: any) {\n // Track error\n this.queryTracker.track(dbId, sql, 0, 0, error.message);\n throw error;\n }\n }\n\n async explainQuery(dbId: string, sql: string, params: any[] = []): Promise<any> {\n await this.ensureConnected(dbId);\n const adapter = this.getAdapter(dbId);\n return adapter.explain(sql, params);\n }\n\n async suggestJoins(dbId: string, tables: string[]): Promise<any[]> {\n const cacheEntry = await this.getSchema(dbId);\n return findJoinPaths(tables, cacheEntry.relationships);\n }\n\n async clearCache(dbId?: string): Promise<void> {\n await this.cache.clear(dbId);\n this.queryTracker.clear(dbId);\n }\n\n async getCacheStatus(dbId?: string): Promise<any[]> {\n return this.cache.getStatus(dbId);\n }\n\n getQueryStats(dbId: string): any {\n return this.queryTracker.getStats(dbId);\n }\n\n getQueryHistory(dbId: string, limit?: number): any[] {\n return this.queryTracker.getHistory(dbId, limit);\n }\n}\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { DatabaseManager } from './database-manager.js';\nimport { ServerConfig } from './types.js';\nimport { getLogger } from './logger.js';\nimport { redactUrl } from './utils.js';\n\nexport class MCPServer {\n private server: Server;\n private logger = getLogger();\n\n constructor(\n private _dbManager: DatabaseManager,\n private _config: ServerConfig\n ) {\n this.server = new Server(\n {\n name: 'mcp-database-server',\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n }\n );\n\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n // List available tools\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'list_databases',\n description: 'List all configured databases with their status',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'introspect_schema',\n description: 'Introspect database schema and cache it',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Database ID to introspect',\n },\n forceRefresh: {\n type: 'boolean',\n description: 'Force refresh even if cached',\n default: false,\n },\n schemaFilter: {\n type: 'object',\n description: 'Optional schema filtering options',\n properties: {\n includeSchemas: {\n type: 'array',\n items: { type: 'string' },\n },\n excludeSchemas: {\n type: 'array',\n items: { type: 'string' },\n },\n includeViews: { type: 'boolean' },\n maxTables: { type: 'number' },\n },\n },\n },\n required: ['dbId'],\n },\n },\n {\n name: 'get_schema',\n description: 'Get cached schema metadata',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Database ID',\n },\n schema: {\n type: 'string',\n description: 'Optional schema name to filter',\n },\n table: {\n type: 'string',\n description: 'Optional table name to filter',\n },\n },\n required: ['dbId'],\n },\n },\n {\n name: 'run_query',\n description: 'Execute SQL query against a database',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Database ID',\n },\n sql: {\n type: 'string',\n description: 'SQL query to execute',\n },\n params: {\n type: 'array',\n description: 'Query parameters',\n items: {},\n },\n limit: {\n type: 'number',\n description: 'Maximum number of rows to return',\n },\n timeoutMs: {\n type: 'number',\n description: 'Query timeout in milliseconds',\n },\n },\n required: ['dbId', 'sql'],\n },\n },\n {\n name: 'explain_query',\n description: 'Get query execution plan',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Database ID',\n },\n sql: {\n type: 'string',\n description: 'SQL query to explain',\n },\n params: {\n type: 'array',\n description: 'Query parameters',\n items: {},\n },\n },\n required: ['dbId', 'sql'],\n },\n },\n {\n name: 'suggest_joins',\n description: 'Suggest join paths between tables based on relationships',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Database ID',\n },\n tables: {\n type: 'array',\n description: 'List of table names to join',\n items: { type: 'string' },\n minItems: 2,\n },\n },\n required: ['dbId', 'tables'],\n },\n },\n {\n name: 'clear_cache',\n description: 'Clear schema cache',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Optional database ID (clears all if omitted)',\n },\n },\n },\n },\n {\n name: 'cache_status',\n description: 'Get cache status and statistics',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Optional database ID',\n },\n },\n },\n },\n {\n name: 'health_check',\n description: 'Check database connectivity and get version info',\n inputSchema: {\n type: 'object',\n properties: {\n dbId: {\n type: 'string',\n description: 'Optional database ID (checks all if omitted)',\n },\n },\n },\n },\n ],\n }));\n\n // Handle tool calls\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'list_databases':\n return await this.handleListDatabases();\n\n case 'introspect_schema':\n return await this.handleIntrospectSchema(args as any);\n\n case 'get_schema':\n return await this.handleGetSchema(args as any);\n\n case 'run_query':\n return await this.handleRunQuery(args as any);\n\n case 'explain_query':\n return await this.handleExplainQuery(args as any);\n\n case 'suggest_joins':\n return await this.handleSuggestJoins(args as any);\n\n case 'clear_cache':\n return await this.handleClearCache(args as any);\n\n case 'cache_status':\n return await this.handleCacheStatus(args as any);\n\n case 'health_check':\n return await this.handleHealthCheck(args as any);\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (error: any) {\n this.logger.error({ tool: name, error }, 'Tool execution failed');\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: error.message,\n code: error.code || 'TOOL_ERROR',\n }),\n },\n ],\n };\n }\n });\n\n // List resources (cached schemas)\n this.server.setRequestHandler(ListResourcesRequestSchema, async () => {\n const statuses = await this._dbManager.getCacheStatus();\n const resources = statuses\n .filter((s) => s.exists)\n .map((s) => ({\n uri: `schema://${s.dbId}`,\n name: `Schema: ${s.dbId}`,\n description: `Cached schema for ${s.dbId} (${s.tableCount} tables, ${s.relationshipCount} relationships)`,\n mimeType: 'application/json',\n }));\n\n return { resources };\n });\n\n // Read resource (return cached schema)\n this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const uri = request.params.uri;\n const match = uri.match(/^schema:\\/\\/(.+)$/);\n\n if (!match) {\n throw new Error(`Invalid resource URI: ${uri}`);\n }\n\n const dbId = match[1];\n const cacheEntry = await this._dbManager.getSchema(dbId);\n\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(cacheEntry, null, 2),\n },\n ],\n };\n });\n }\n\n private async handleListDatabases() {\n const configs = this._dbManager.getConfigs();\n const statuses = await Promise.all(\n configs.map(async (config) => {\n const connected = await this._dbManager.testConnection(config.id);\n const cacheStatus = (await this._dbManager.getCacheStatus(config.id))[0];\n\n return {\n id: config.id,\n type: config.type,\n url: this._config.security?.redactSecrets ? redactUrl(config.url || '') : config.url,\n connected,\n cached: cacheStatus?.exists || false,\n cacheAge: cacheStatus?.age,\n version: cacheStatus?.version,\n };\n })\n );\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(statuses, null, 2),\n },\n ],\n };\n }\n\n private async handleIntrospectSchema(args: {\n dbId: string;\n forceRefresh?: boolean;\n schemaFilter?: any;\n }) {\n const result = await this._dbManager.introspectSchema(\n args.dbId,\n args.forceRefresh || false,\n args.schemaFilter\n );\n\n const summary = {\n dbId: args.dbId,\n version: result.schema.version,\n introspectedAt: result.schema.introspectedAt,\n schemas: result.schema.schemas.map((s) => ({\n name: s.name,\n tableCount: s.tables.length,\n viewCount: s.tables.filter((t) => t.type === 'view').length,\n })),\n totalTables: result.schema.schemas.reduce((sum, s) => sum + s.tables.length, 0),\n totalRelationships: result.relationships.length,\n };\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(summary, null, 2),\n },\n ],\n };\n }\n\n private async handleGetSchema(args: { dbId: string; schema?: string; table?: string }) {\n const cacheEntry = await this._dbManager.getSchema(args.dbId);\n let result: any = cacheEntry.schema;\n\n // Filter by schema\n if (args.schema) {\n result = {\n ...result,\n schemas: result.schemas.filter((s: any) => s.name === args.schema),\n };\n }\n\n // Filter by table\n if (args.table) {\n result = {\n ...result,\n schemas: result.schemas.map((s: any) => ({\n ...s,\n tables: s.tables.filter((t: any) => t.name === args.table),\n })),\n };\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n private async handleRunQuery(args: {\n dbId: string;\n sql: string;\n params?: any[];\n limit?: number;\n timeoutMs?: number;\n }) {\n let sql = args.sql;\n\n // Apply row limit if specified\n if (args.limit && !sql.toUpperCase().includes('LIMIT')) {\n sql += ` LIMIT ${args.limit}`;\n }\n\n const result = await this._dbManager.runQuery(args.dbId, sql, args.params, args.timeoutMs);\n\n // Get relevant relationships for the query\n const cacheEntry = await this._dbManager.getSchema(args.dbId);\n const queryStats = this._dbManager.getQueryStats(args.dbId);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n ...result,\n metadata: {\n relationships: cacheEntry.relationships.filter((r) =>\n result.columns.some(\n (col) =>\n col.includes(r.fromTable) ||\n col.includes(r.toTable)\n )\n ),\n queryStats,\n },\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n private async handleExplainQuery(args: { dbId: string; sql: string; params?: any[] }) {\n const result = await this._dbManager.explainQuery(args.dbId, args.sql, args.params);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n private async handleSuggestJoins(args: { dbId: string; tables: string[] }) {\n const joinPaths = await this._dbManager.suggestJoins(args.dbId, args.tables);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(joinPaths, null, 2),\n },\n ],\n };\n }\n\n private async handleClearCache(args: { dbId?: string }) {\n await this._dbManager.clearCache(args.dbId);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n success: true,\n message: args.dbId ? `Cache cleared for ${args.dbId}` : 'All caches cleared',\n }),\n },\n ],\n };\n }\n\n private async handleCacheStatus(args: { dbId?: string }) {\n const statuses = await this._dbManager.getCacheStatus(args.dbId);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(statuses, null, 2),\n },\n ],\n };\n }\n\n private async handleHealthCheck(args: { dbId?: string }) {\n const configs = args.dbId\n ? [this._dbManager.getConfig(args.dbId)!]\n : this._dbManager.getConfigs();\n\n const results = await Promise.all(\n configs.map(async (config) => {\n try {\n const connected = await this._dbManager.testConnection(config.id);\n const version = connected ? await this._dbManager.getVersion(config.id) : 'N/A';\n\n return {\n dbId: config.id,\n healthy: connected,\n version,\n };\n } catch (error: any) {\n return {\n dbId: config.id,\n healthy: false,\n error: error.message,\n };\n }\n })\n );\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2),\n },\n ],\n };\n }\n\n async start(): Promise<void> {\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n this.logger.info('MCP server started');\n }\n}\n"],"mappings":"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","names":["dirname","join","path","resolve","fs","fs","resolve","version","__filename","__dirname","dirname","join","logger"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/types.ts","../src/utils.ts","../src/adapters/postgres.ts","../src/logger.ts","../src/adapters/base.ts","../src/adapters/mysql.ts","../src/adapters/sqlite.ts","../src/adapters/mssql.ts","../src/adapters/oracle.ts","../src/adapters/index.ts","../src/cache.ts","../src/query-optimizer.ts","../src/query-tracker.ts","../src/database-manager.ts","../src/mcp-server.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport dotenv from 'dotenv';\r\nimport { parseArgs } from 'util';\r\nimport { readFileSync, existsSync } from 'fs';\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname, join } from 'path';\r\nimport { loadConfig, findConfigFile } from './config.js';\r\nimport { DatabaseManager } from './database-manager.js';\r\nimport { MCPServer } from './mcp-server.js';\r\nimport { initLogger, getLogger } from './logger.js';\r\n\r\n// Load environment variables\r\ndotenv.config();\r\n\r\n// Get package version\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\nconst packageJson = JSON.parse(\r\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\r\n);\r\nconst version = packageJson.version;\r\n\r\nasync function main() {\r\n try {\r\n // Parse command line arguments\r\n const { values } = parseArgs({\r\n options: {\r\n config: {\r\n type: 'string',\r\n short: 'c',\r\n },\r\n help: {\r\n type: 'boolean',\r\n short: 'h',\r\n },\r\n version: {\r\n type: 'boolean',\r\n short: 'v',\r\n },\r\n },\r\n });\r\n\r\n if (values.version) {\r\n console.log(version);\r\n process.exit(0);\r\n }\r\n\r\n if (values.help) {\r\n console.log(`\r\nmcp-database-server - Model Context Protocol Server for SQL Databases\r\n\r\nUsage:\r\n mcp-database-server [options]\r\n\r\nOptions:\r\n -c, --config <path> Path to configuration file (if not specified, searches for .mcp-database-server.config from project root upwards)\r\n -h, --help Show this help message\r\n -v, --version Show version number\r\n\r\nConfiguration:\r\n The config file should be a JSON file with database configurations.\r\n See mcp-database-server.config.example for reference.\r\n\r\nEnvironment Variables:\r\n You can use environment variable interpolation in the config file:\r\n Example: \"url\": \"\\${DB_URL_POSTGRES}\"\r\n\r\nExamples:\r\n mcp-database-server --config ./my-config.json\r\n mcp-database-server -c ./config/production.json\r\n `);\r\n process.exit(0);\r\n }\r\n\r\n // Load configuration\r\n let configPath: string;\r\n \r\n if (values.config) {\r\n configPath = values.config;\r\n if (!existsSync(configPath)) {\r\n console.error(`Error: Specified config file ${configPath} not found`);\r\n process.exit(1);\r\n }\r\n } else {\r\n // No config specified, search upwards for .mcp-database-server.config\r\n const foundPath = findConfigFile('.mcp-database-server.config');\r\n if (foundPath) {\r\n configPath = foundPath;\r\n } else {\r\n console.error('Error: No config file specified, and .mcp-database-server.config not found');\r\n console.error('Searched in current directory and all parent directories');\r\n console.error('\\nTo create a config file:');\r\n console.error(' cp mcp-database-server.config.example .mcp-database-server.config');\r\n console.error('\\nOr specify a custom path:');\r\n console.error(' mcp-database-server --config /path/to/config.json');\r\n process.exit(1);\r\n }\r\n }\r\n \r\n const config = await loadConfig(configPath);\r\n\r\n // Initialize logger\r\n initLogger(config.logging?.level || 'info', config.logging?.pretty || false);\r\n const logger = getLogger();\r\n\r\n logger.info({ configPath }, 'Configuration loaded');\r\n\r\n // Initialize database manager\r\n const dbManager = new DatabaseManager(config.databases, {\r\n cacheDir: config.cache?.directory || '.sql-mcp-cache',\r\n cacheTtlMinutes: config.cache?.ttlMinutes || 10,\r\n allowWrite: config.security?.allowWrite || false,\r\n allowedWriteOperations: config.security?.allowedWriteOperations,\r\n disableDangerousOperations: config.security?.disableDangerousOperations ?? true,\r\n });\r\n\r\n await dbManager.init();\r\n\r\n // Create and start MCP server\r\n const mcpServer = new MCPServer(dbManager, config);\r\n await mcpServer.start();\r\n\r\n // Graceful shutdown\r\n const shutdown = async (signal: string) => {\r\n logger.info({ signal }, 'Shutting down...');\r\n await dbManager.shutdown();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', () => shutdown('SIGINT'));\r\n process.on('SIGTERM', () => shutdown('SIGTERM'));\r\n } catch (error: any) {\r\n console.error('Fatal error:', error.message);\r\n if (error.details) {\r\n console.error('Details:', JSON.stringify(error.details, null, 2));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\nmain();\r\n","import fs from 'fs/promises';\r\nimport { existsSync } from 'fs';\r\nimport { dirname, resolve, join } from 'path';\r\nimport { ServerConfig, ServerConfigSchema, ConfigError } from './types.js';\r\nimport { interpolateEnv } from './utils.js';\r\n\r\n/**\r\n * Find project root by looking for common project markers\r\n * @param startDir - Directory to start searching from (defaults to cwd)\r\n * @returns Absolute path to project root or null if not found\r\n */\r\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\r\n const projectMarkers = ['package.json', '.git', 'tsconfig.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'];\r\n let currentDir = resolve(startDir);\r\n\r\n while (true) {\r\n for (const marker of projectMarkers) {\r\n if (existsSync(join(currentDir, marker))) {\r\n return currentDir;\r\n }\r\n }\r\n\r\n const parentDir = dirname(currentDir);\r\n \r\n // Reached filesystem root (parent equals current)\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n\r\n // Move up one directory\r\n currentDir = parentDir;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Find config file by traversing up the directory tree\r\n * @param fileName - Name of the config file to find\r\n * @param startDir - Directory to start searching from (defaults to cwd)\r\n * @returns Absolute path to config file or null if not found\r\n */\r\nexport function findConfigFile(fileName: string, startDir: string = process.cwd()): string | null {\r\n // First try to find project root and search from there\r\n const projectRoot = findProjectRoot(startDir);\r\n if (projectRoot) {\r\n const configFromProjectRoot = findConfigFileFromDir(fileName, projectRoot);\r\n if (configFromProjectRoot) {\r\n return configFromProjectRoot;\r\n }\r\n }\r\n\r\n // Fallback to searching from the original start directory\r\n return findConfigFileFromDir(fileName, startDir);\r\n}\r\n\r\n/**\r\n * Find config file by traversing up from a specific directory\r\n * @param fileName - Name of the config file to find\r\n * @param startDir - Directory to start searching from\r\n * @returns Absolute path to config file or null if not found\r\n */\r\nfunction findConfigFileFromDir(fileName: string, startDir: string): string | null {\r\n let currentDir = resolve(startDir);\r\n\r\n while (true) {\r\n const configPath = join(currentDir, fileName);\r\n \r\n if (existsSync(configPath)) {\r\n return configPath;\r\n }\r\n\r\n const parentDir = dirname(currentDir);\r\n \r\n // Reached filesystem root (parent equals current)\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n\r\n // Move up one directory\r\n currentDir = parentDir;\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport async function loadConfig(configPath: string): Promise<ServerConfig> {\r\n try {\r\n const content = await fs.readFile(configPath, 'utf-8');\r\n const rawConfig = JSON.parse(content);\r\n\r\n // Interpolate environment variables in all string values\r\n const interpolatedConfig = interpolateConfigValues(rawConfig);\r\n\r\n // Validate with Zod\r\n const config = ServerConfigSchema.parse(interpolatedConfig);\r\n\r\n // Additional validation\r\n validateDatabaseConfigs(config);\r\n\r\n return config;\r\n } catch (error: any) {\r\n if (error.name === 'ZodError') {\r\n throw new ConfigError('Configuration validation failed', error.errors);\r\n }\r\n throw new ConfigError(`Failed to load config from ${configPath}: ${error.message}`);\r\n }\r\n}\r\n\r\nfunction interpolateConfigValues(obj: any): any {\r\n if (typeof obj === 'string') {\r\n return interpolateEnv(obj);\r\n }\r\n \r\n if (Array.isArray(obj)) {\r\n return obj.map(interpolateConfigValues);\r\n }\r\n \r\n if (obj && typeof obj === 'object') {\r\n const result: any = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n result[key] = interpolateConfigValues(value);\r\n }\r\n return result;\r\n }\r\n \r\n return obj;\r\n}\r\n\r\nfunction validateDatabaseConfigs(config: ServerConfig): void {\r\n const ids = new Set<string>();\r\n\r\n for (const db of config.databases) {\r\n // Check for duplicate IDs\r\n if (ids.has(db.id)) {\r\n throw new ConfigError(`Duplicate database ID: ${db.id}`);\r\n }\r\n ids.add(db.id);\r\n\r\n // Validate database-specific requirements\r\n if (db.type === 'sqlite') {\r\n if (!db.path && !db.url) {\r\n throw new ConfigError(`SQLite database ${db.id} requires 'path' or 'url'`);\r\n }\r\n } else {\r\n if (!db.url) {\r\n throw new ConfigError(`Database ${db.id} requires 'url'`);\r\n }\r\n }\r\n }\r\n}\r\n","import { z } from 'zod';\r\n\r\n// Database types\r\nexport type DatabaseType = 'postgres' | 'mysql' | 'mssql' | 'sqlite' | 'oracle';\r\n\r\n// Connection pool settings\r\nexport const ConnectionPoolSchema = z.object({\r\n min: z.number().min(0).optional(),\r\n max: z.number().min(1).optional(),\r\n idleTimeoutMillis: z.number().min(0).optional(),\r\n connectionTimeoutMillis: z.number().min(0).optional(),\r\n});\r\n\r\nexport type ConnectionPool = z.infer<typeof ConnectionPoolSchema>;\r\n\r\n// Introspection options\r\nexport const IntrospectionOptionsSchema = z.object({\r\n includeViews: z.boolean().optional().default(true),\r\n includeRoutines: z.boolean().optional().default(false),\r\n maxTables: z.number().min(1).optional(),\r\n excludeSchemas: z.array(z.string()).optional(),\r\n includeSchemas: z.array(z.string()).optional(),\r\n});\r\n\r\nexport type IntrospectionOptions = z.infer<typeof IntrospectionOptionsSchema>;\r\n\r\n// Database configuration\r\nexport const DatabaseConfigSchema = z.object({\r\n id: z.string().min(1),\r\n type: z.enum(['postgres', 'mysql', 'mssql', 'sqlite', 'oracle']),\r\n url: z.string().optional(),\r\n path: z.string().optional(),\r\n readOnly: z.boolean().optional().default(true),\r\n pool: ConnectionPoolSchema.optional(),\r\n introspection: IntrospectionOptionsSchema.optional(),\r\n eagerConnect: z.boolean().optional().default(false),\r\n});\r\n\r\nexport type DatabaseConfig = z.infer<typeof DatabaseConfigSchema>;\r\n\r\n// Server configuration\r\nexport const ServerConfigSchema = z.object({\r\n databases: z.array(DatabaseConfigSchema).min(1),\r\n cache: z\r\n .object({\r\n directory: z.string().optional().default('.sql-mcp-cache'),\r\n ttlMinutes: z.number().min(0).optional().default(10),\r\n })\r\n .optional()\r\n .default({ directory: '.sql-mcp-cache', ttlMinutes: 10 }),\r\n security: z\r\n .object({\r\n allowWrite: z.boolean().optional().default(false),\r\n allowedWriteOperations: z.array(z.string()).optional(),\r\n disableDangerousOperations: z.boolean().optional().default(true),\r\n redactSecrets: z.boolean().optional().default(true),\r\n })\r\n .optional()\r\n .default({ allowWrite: false, disableDangerousOperations: true, redactSecrets: true }),\r\n logging: z\r\n .object({\r\n level: z.enum(['trace', 'debug', 'info', 'warn', 'error']).optional().default('info'),\r\n pretty: z.boolean().optional().default(false),\r\n })\r\n .optional()\r\n .default({ level: 'info', pretty: false }),\r\n});\r\n\r\nexport type ServerConfig = z.infer<typeof ServerConfigSchema>;\r\n\r\n// Schema metadata types\r\nexport interface ColumnMetadata {\r\n name: string;\r\n dataType: string;\r\n nullable: boolean;\r\n defaultValue?: string;\r\n maxLength?: number;\r\n precision?: number;\r\n scale?: number;\r\n isAutoIncrement?: boolean;\r\n comment?: string;\r\n}\r\n\r\nexport interface IndexMetadata {\r\n name: string;\r\n columns: string[];\r\n isUnique: boolean;\r\n isPrimary: boolean;\r\n}\r\n\r\nexport interface ForeignKeyMetadata {\r\n name: string;\r\n columns: string[];\r\n referencedSchema: string;\r\n referencedTable: string;\r\n referencedColumns: string[];\r\n onDelete?: string;\r\n onUpdate?: string;\r\n}\r\n\r\nexport interface TableMetadata {\r\n schema: string;\r\n name: string;\r\n type: 'table' | 'view';\r\n columns: ColumnMetadata[];\r\n primaryKey?: IndexMetadata;\r\n indexes: IndexMetadata[];\r\n foreignKeys: ForeignKeyMetadata[];\r\n comment?: string;\r\n}\r\n\r\nexport interface SchemaMetadata {\r\n name: string;\r\n tables: TableMetadata[];\r\n}\r\n\r\nexport interface DatabaseSchema {\r\n dbId: string;\r\n dbType: DatabaseType;\r\n schemas: SchemaMetadata[];\r\n introspectedAt: Date;\r\n version: string; // ETag/version based on content\r\n}\r\n\r\n// Relationship types\r\nexport interface Relationship {\r\n fromSchema: string;\r\n fromTable: string;\r\n fromColumns: string[];\r\n toSchema: string;\r\n toTable: string;\r\n toColumns: string[];\r\n type: 'foreign_key' | 'inferred';\r\n confidence?: number; // For inferred relationships\r\n}\r\n\r\n// Query result types\r\nexport interface QueryResult {\r\n rows: any[];\r\n columns: string[];\r\n rowCount: number;\r\n executionTimeMs: number;\r\n affectedRows?: number;\r\n}\r\n\r\nexport interface ExplainResult {\r\n plan: any;\r\n formattedPlan?: string;\r\n}\r\n\r\n// Query tracking\r\nexport interface QueryHistoryEntry {\r\n timestamp: Date;\r\n sql: string;\r\n tables: string[];\r\n executionTimeMs: number;\r\n rowCount: number;\r\n error?: string;\r\n explainPlan?: any; // Execution plan for performance analysis\r\n queryComplexity?: QueryComplexity; // Complexity metrics\r\n suggestedIndexes?: IndexRecommendation[]; // Index suggestions\r\n rewrittenQuery?: string; // Optimized query suggestion\r\n performanceScore?: number; // 0-100 performance score\r\n}\r\n\r\n// Query complexity analysis\r\nexport interface QueryComplexity {\r\n selectColumns: number;\r\n whereConditions: number;\r\n joinCount: number;\r\n subqueryCount: number;\r\n hasAggregations: boolean;\r\n hasDistinct: boolean;\r\n hasOrderBy: boolean;\r\n hasGroupBy: boolean;\r\n estimatedComplexity: 'simple' | 'medium' | 'complex' | 'very_complex';\r\n}\r\n\r\n// Index recommendation\r\nexport interface IndexRecommendation {\r\n table: string;\r\n columns: string[];\r\n type: 'single' | 'composite' | 'covering';\r\n reason: string;\r\n impact: 'high' | 'medium' | 'low';\r\n existingIndex?: string; // If similar index already exists\r\n}\r\n\r\n// Query performance profile\r\nexport interface QueryPerformanceProfile {\r\n queryId: string;\r\n sql: string;\r\n executionTimeMs: number;\r\n rowCount: number;\r\n bottlenecks: PerformanceBottleneck[];\r\n recommendations: PerformanceRecommendation[];\r\n overallScore: number; // 0-100\r\n}\r\n\r\n// Performance bottleneck\r\nexport interface PerformanceBottleneck {\r\n type: 'table_scan' | 'index_scan' | 'sort' | 'join' | 'subquery' | 'aggregation';\r\n severity: 'critical' | 'high' | 'medium' | 'low';\r\n description: string;\r\n estimatedCost: number;\r\n table?: string;\r\n columns?: string[];\r\n}\r\n\r\n// Performance recommendation\r\nexport interface PerformanceRecommendation {\r\n type: 'add_index' | 'rewrite_query' | 'optimize_join' | 'add_where_clause' | 'use_union' | 'materialize_view';\r\n description: string;\r\n sql?: string; // Suggested SQL change\r\n impact: 'high' | 'medium' | 'low';\r\n effort: 'low' | 'medium' | 'high';\r\n}\r\n\r\n// Slow query alert\r\nexport interface SlowQueryAlert {\r\n dbId: string;\r\n queryId: string;\r\n sql: string;\r\n executionTimeMs: number;\r\n thresholdMs: number;\r\n timestamp: Date;\r\n frequency: number; // How many times this query has been slow\r\n recommendations: PerformanceRecommendation[];\r\n}\r\n\r\n// Query optimization result\r\nexport interface QueryOptimizationResult {\r\n originalQuery: string;\r\n optimizedQuery: string;\r\n improvements: string[];\r\n performanceGain: number; // Estimated percentage improvement\r\n confidence: 'high' | 'medium' | 'low';\r\n}\r\n\r\n// Join suggestion\r\nexport interface JoinPath {\r\n tables: string[];\r\n joins: Array<{\r\n fromTable: string;\r\n toTable: string;\r\n relationship: Relationship;\r\n joinCondition: string;\r\n }>;\r\n}\r\n\r\n// Database adapter interface\r\nexport interface DatabaseAdapter {\r\n connect(): Promise<void>;\r\n disconnect(): Promise<void>;\r\n introspect(options?: IntrospectionOptions): Promise<DatabaseSchema>;\r\n query(sql: string, params?: any[], timeoutMs?: number): Promise<QueryResult>;\r\n explain(sql: string, params?: any[]): Promise<ExplainResult>;\r\n testConnection(): Promise<boolean>;\r\n getVersion(): Promise<string>;\r\n}\r\n\r\n// Error types\r\nexport class DatabaseError extends Error {\r\n constructor(\r\n message: string,\r\n public _code: string,\r\n public _dbId?: string,\r\n public _originalError?: Error\r\n ) {\r\n super(message);\r\n this.name = 'DatabaseError';\r\n }\r\n}\r\n\r\nexport class ConfigError extends Error {\r\n constructor(message: string, public _details?: any) {\r\n super(message);\r\n this.name = 'ConfigError';\r\n }\r\n}\r\n\r\nexport class CacheError extends Error {\r\n constructor(message: string, public _originalError?: Error) {\r\n super(message);\r\n this.name = 'CacheError';\r\n }\r\n}\r\n","import crypto from 'crypto';\r\nimport { URL } from 'url';\r\nimport { Relationship, DatabaseSchema } from './types.js';\r\n\r\n/**\r\n * Redact secrets from URLs and connection strings\r\n */\r\nexport function redactUrl(url: string): string {\r\n try {\r\n // Handle various URL formats\r\n if (url.includes('://')) {\r\n const urlObj = new URL(url);\r\n if (urlObj.password) {\r\n urlObj.password = '***';\r\n }\r\n if (urlObj.username && urlObj.password) {\r\n return urlObj.toString();\r\n }\r\n }\r\n \r\n // Handle SQL Server connection strings\r\n if (url.includes('Password=')) {\r\n return url.replace(/(Password=)[^;]+/gi, '$1***');\r\n }\r\n \r\n // Handle Oracle connection strings\r\n if (url.includes('/') && url.includes('@')) {\r\n return url.replace(/\\/[^@]+@/, '/***@');\r\n }\r\n \r\n return url;\r\n } catch {\r\n // If parsing fails, be safe and redact everything after ://\r\n return url.replace(/:\\/\\/[^@]*@/, '://***@');\r\n }\r\n}\r\n\r\n/**\r\n * Interpolate environment variables in config values\r\n */\r\nexport function interpolateEnv(value: string): string {\r\n return value.replace(/\\$\\{([^}]+)\\}/g, (_, varName) => {\r\n return process.env[varName] || '';\r\n });\r\n}\r\n\r\n/**\r\n * Generate a stable version/ETag from schema content\r\n */\r\nexport function generateSchemaVersion(schema: DatabaseSchema): string {\r\n const hash = crypto.createHash('sha256');\r\n \r\n // Create a stable representation of the schema\r\n const schemaData = {\r\n dbType: schema.dbType,\r\n schemas: schema.schemas.map((s) => ({\r\n name: s.name,\r\n tables: s.tables\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n .map((t) => ({\r\n name: t.name,\r\n type: t.type,\r\n columns: t.columns\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n .map((c) => ({\r\n name: c.name,\r\n dataType: c.dataType,\r\n nullable: c.nullable,\r\n })),\r\n foreignKeys: t.foreignKeys.sort((a, b) => a.name.localeCompare(b.name)),\r\n })),\r\n })),\r\n };\r\n \r\n hash.update(JSON.stringify(schemaData));\r\n return hash.digest('hex').substring(0, 16);\r\n}\r\n\r\n/**\r\n * Infer relationships from column naming patterns\r\n */\r\nexport function inferRelationships(schema: DatabaseSchema): Relationship[] {\r\n const relationships: Relationship[] = [];\r\n \r\n // Build a lookup of tables and their primary keys\r\n const tableLookup = new Map<string, { schema: string; pk: string[] }>();\r\n \r\n for (const schemaObj of schema.schemas) {\r\n for (const table of schemaObj.tables) {\r\n const fullName = `${schemaObj.name}.${table.name}`;\r\n const pk = table.primaryKey?.columns || [];\r\n tableLookup.set(table.name.toLowerCase(), { schema: schemaObj.name, pk });\r\n tableLookup.set(fullName.toLowerCase(), { schema: schemaObj.name, pk });\r\n }\r\n }\r\n \r\n // Look for FK patterns in each table\r\n for (const schemaObj of schema.schemas) {\r\n for (const table of schemaObj.tables) {\r\n for (const column of table.columns) {\r\n const columnName = column.name.toLowerCase();\r\n \r\n // Pattern 1: <table>_id or <table>Id\r\n const patterns = [\r\n /^(.+?)_id$/,\r\n /^(.+?)id$/i,\r\n ];\r\n \r\n for (const pattern of patterns) {\r\n const match = columnName.match(pattern);\r\n if (match) {\r\n const referencedTableName = match[1].toLowerCase();\r\n const referencedTable = tableLookup.get(referencedTableName);\r\n \r\n if (referencedTable && referencedTable.pk.length > 0) {\r\n // Only infer if we have a reasonable confidence\r\n relationships.push({\r\n fromSchema: schemaObj.name,\r\n fromTable: table.name,\r\n fromColumns: [column.name],\r\n toSchema: referencedTable.schema,\r\n toTable: referencedTableName,\r\n toColumns: referencedTable.pk,\r\n type: 'inferred',\r\n confidence: 0.7,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n return relationships;\r\n}\r\n\r\n/**\r\n * Extract table names from SQL (best effort)\r\n */\r\nexport function extractTableNames(sql: string): string[] {\r\n const tables = new Set<string>();\r\n \r\n // Simple regex-based extraction (best effort)\r\n // Matches: FROM table, JOIN table, INTO table, UPDATE table, DELETE FROM table\r\n const patterns = [\r\n /(?:FROM|JOIN|INTO|UPDATE)\\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)?)/gi,\r\n /DELETE\\s+FROM\\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)?)/gi,\r\n ];\r\n \r\n for (const pattern of patterns) {\r\n const matches = sql.matchAll(pattern);\r\n for (const match of matches) {\r\n if (match[1]) {\r\n tables.add(match[1].toLowerCase());\r\n }\r\n }\r\n }\r\n \r\n return Array.from(tables);\r\n}\r\n\r\n/**\r\n * Detect if SQL is a write operation\r\n */\r\nexport function isWriteOperation(sql: string): boolean {\r\n const upperSql = sql.trim().toUpperCase();\r\n const writeKeywords = [\r\n 'INSERT',\r\n 'UPDATE',\r\n 'DELETE',\r\n 'CREATE',\r\n 'ALTER',\r\n 'DROP',\r\n 'TRUNCATE',\r\n 'REPLACE',\r\n 'MERGE',\r\n ];\r\n \r\n for (const keyword of writeKeywords) {\r\n if (upperSql.startsWith(keyword)) {\r\n return true;\r\n }\r\n }\r\n \r\n return false;\r\n}\r\n\r\n/**\r\n * Find join paths between tables using relationship graph\r\n */\r\nexport function findJoinPaths(\r\n tables: string[],\r\n relationships: Relationship[],\r\n maxDepth = 3\r\n): any[] {\r\n if (tables.length < 2) {\r\n return [];\r\n }\r\n \r\n const paths: any[] = [];\r\n \r\n // Build adjacency list\r\n const graph = new Map<string, Relationship[]>();\r\n for (const rel of relationships) {\r\n const fromKey = `${rel.fromSchema}.${rel.fromTable}`.toLowerCase();\r\n const toKey = `${rel.toSchema}.${rel.toTable}`.toLowerCase();\r\n \r\n if (!graph.has(fromKey)) {\r\n graph.set(fromKey, []);\r\n }\r\n graph.get(fromKey)!.push(rel);\r\n \r\n // Reverse direction\r\n const reverseRel: Relationship = {\r\n ...rel,\r\n fromSchema: rel.toSchema,\r\n fromTable: rel.toTable,\r\n fromColumns: rel.toColumns,\r\n toSchema: rel.fromSchema,\r\n toTable: rel.fromTable,\r\n toColumns: rel.fromColumns,\r\n };\r\n \r\n if (!graph.has(toKey)) {\r\n graph.set(toKey, []);\r\n }\r\n graph.get(toKey)!.push(reverseRel);\r\n }\r\n \r\n // Simple BFS to find shortest path between first two tables\r\n const start = tables[0].toLowerCase();\r\n const end = tables[1].toLowerCase();\r\n \r\n const queue: Array<{ current: string; path: Relationship[] }> = [{ current: start, path: [] }];\r\n const visited = new Set<string>([start]);\r\n \r\n while (queue.length > 0) {\r\n const { current, path } = queue.shift()!;\r\n \r\n if (path.length >= maxDepth) {\r\n continue;\r\n }\r\n \r\n const neighbors = graph.get(current) || [];\r\n for (const rel of neighbors) {\r\n const next = `${rel.toSchema}.${rel.toTable}`.toLowerCase();\r\n \r\n if (next === end) {\r\n paths.push({\r\n tables: [start, ...path.map((r) => `${r.toSchema}.${r.toTable}`), end],\r\n joins: [...path, rel],\r\n });\r\n continue;\r\n }\r\n \r\n if (!visited.has(next)) {\r\n visited.add(next);\r\n queue.push({ current: next, path: [...path, rel] });\r\n }\r\n }\r\n }\r\n \r\n return paths;\r\n}\r\n","import pg from 'pg';\r\nimport { BaseAdapter } from './base.js';\r\nimport {\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n TableMetadata,\r\n ColumnMetadata,\r\n IndexMetadata,\r\n ForeignKeyMetadata,\r\n SchemaMetadata,\r\n} from '../types.js';\r\nimport { generateSchemaVersion } from '../utils.js';\r\n\r\nconst { Pool } = pg;\r\n\r\nexport class PostgresAdapter extends BaseAdapter {\r\n private pool?: pg.Pool;\r\n\r\n async connect(): Promise<void> {\r\n try {\r\n this.pool = new Pool({\r\n connectionString: this._config.url,\r\n min: this._config.pool?.min || 2,\r\n max: this._config.pool?.max || 10,\r\n idleTimeoutMillis: this._config.pool?.idleTimeoutMillis || 30000,\r\n connectionTimeoutMillis: this._config.pool?.connectionTimeoutMillis || 10000,\r\n });\r\n\r\n // Test connection\r\n const client = await this.pool.connect();\r\n client.release();\r\n\r\n this.connected = true;\r\n this.logger.info({ dbId: this._config.id }, 'PostgreSQL connected');\r\n } catch (error) {\r\n this.handleError(error, 'connect');\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n if (this.pool) {\r\n await this.pool.end();\r\n this.pool = undefined;\r\n this.connected = false;\r\n this.logger.info({ dbId: this._config.id }, 'PostgreSQL disconnected');\r\n }\r\n }\r\n\r\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const schemas = await this.getSchemas(options);\r\n const dbSchema: DatabaseSchema = {\r\n dbId: this._config.id,\r\n dbType: 'postgres',\r\n schemas,\r\n introspectedAt: new Date(),\r\n version: '',\r\n };\r\n\r\n dbSchema.version = generateSchemaVersion(dbSchema);\r\n return dbSchema;\r\n } catch (error) {\r\n this.handleError(error, 'introspect');\r\n }\r\n }\r\n\r\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\r\n const result: SchemaMetadata[] = [];\r\n\r\n // Get all schemas\r\n const schemasQuery = `\r\n SELECT schema_name\r\n FROM information_schema.schemata\r\n WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\r\n ORDER BY schema_name\r\n `;\r\n\r\n const schemasResult = await this.pool!.query(schemasQuery);\r\n let schemaNames = schemasResult.rows.map((r) => r.schema_name);\r\n\r\n // Apply filters\r\n if (options?.includeSchemas && options.includeSchemas.length > 0) {\r\n schemaNames = schemaNames.filter((s) => options.includeSchemas!.includes(s));\r\n }\r\n if (options?.excludeSchemas && options.excludeSchemas.length > 0) {\r\n schemaNames = schemaNames.filter((s) => !options.excludeSchemas!.includes(s));\r\n }\r\n\r\n for (const schemaName of schemaNames) {\r\n const tables = await this.getTables(schemaName, options);\r\n result.push({\r\n name: schemaName,\r\n tables,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getTables(\r\n schemaName: string,\r\n options?: IntrospectionOptions\r\n ): Promise<TableMetadata[]> {\r\n const result: TableMetadata[] = [];\r\n\r\n // Get tables and views\r\n let tableTypes = \"'BASE TABLE'\";\r\n if (options?.includeViews) {\r\n tableTypes += \",'VIEW'\";\r\n }\r\n\r\n const tablesQuery = `\r\n SELECT table_name, table_type\r\n FROM information_schema.tables\r\n WHERE table_schema = $1 AND table_type IN (${tableTypes})\r\n ORDER BY table_name\r\n ${options?.maxTables ? `LIMIT ${options.maxTables}` : ''}\r\n `;\r\n\r\n const tablesResult = await this.pool!.query(tablesQuery, [schemaName]);\r\n\r\n for (const row of tablesResult.rows) {\r\n const columns = await this.getColumns(schemaName, row.table_name);\r\n const indexes = await this.getIndexes(schemaName, row.table_name);\r\n const foreignKeys = await this.getForeignKeys(schemaName, row.table_name);\r\n\r\n const primaryKey = indexes.find((idx) => idx.isPrimary);\r\n\r\n result.push({\r\n schema: schemaName,\r\n name: row.table_name,\r\n type: row.table_type === 'VIEW' ? 'view' : 'table',\r\n columns,\r\n primaryKey,\r\n indexes: indexes.filter((idx) => !idx.isPrimary),\r\n foreignKeys,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\r\n const query = `\r\n SELECT\r\n column_name,\r\n data_type,\r\n is_nullable,\r\n column_default,\r\n character_maximum_length,\r\n numeric_precision,\r\n numeric_scale,\r\n is_identity\r\n FROM information_schema.columns\r\n WHERE table_schema = $1 AND table_name = $2\r\n ORDER BY ordinal_position\r\n `;\r\n\r\n const result = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return result.rows.map((row) => ({\r\n name: row.column_name,\r\n dataType: row.data_type,\r\n nullable: row.is_nullable === 'YES',\r\n defaultValue: row.column_default,\r\n maxLength: row.character_maximum_length,\r\n precision: row.numeric_precision,\r\n scale: row.numeric_scale,\r\n isAutoIncrement: row.is_identity === 'YES',\r\n }));\r\n }\r\n\r\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\r\n const query = `\r\n SELECT\r\n i.relname AS index_name,\r\n ix.indisunique AS is_unique,\r\n ix.indisprimary AS is_primary,\r\n array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) AS column_names\r\n FROM pg_class t\r\n JOIN pg_index ix ON t.oid = ix.indrelid\r\n JOIN pg_class i ON i.oid = ix.indexrelid\r\n JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\r\n JOIN pg_namespace n ON n.oid = t.relnamespace\r\n WHERE n.nspname = $1 AND t.relname = $2\r\n GROUP BY i.relname, ix.indisunique, ix.indisprimary\r\n `;\r\n\r\n const result = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return result.rows.map((row) => ({\r\n name: row.index_name,\r\n columns: row.column_names,\r\n isUnique: row.is_unique,\r\n isPrimary: row.is_primary,\r\n }));\r\n }\r\n\r\n private async getForeignKeys(\r\n schemaName: string,\r\n tableName: string\r\n ): Promise<ForeignKeyMetadata[]> {\r\n const query = `\r\n SELECT\r\n tc.constraint_name,\r\n array_agg(kcu.column_name ORDER BY kcu.ordinal_position) AS column_names,\r\n ccu.table_schema AS referenced_schema,\r\n ccu.table_name AS referenced_table,\r\n array_agg(ccu.column_name ORDER BY kcu.ordinal_position) AS referenced_columns,\r\n rc.update_rule,\r\n rc.delete_rule\r\n FROM information_schema.table_constraints AS tc\r\n JOIN information_schema.key_column_usage AS kcu\r\n ON tc.constraint_name = kcu.constraint_name\r\n AND tc.table_schema = kcu.table_schema\r\n JOIN information_schema.constraint_column_usage AS ccu\r\n ON ccu.constraint_name = tc.constraint_name\r\n AND ccu.table_schema = tc.table_schema\r\n JOIN information_schema.referential_constraints AS rc\r\n ON rc.constraint_name = tc.constraint_name\r\n AND rc.constraint_schema = tc.table_schema\r\n WHERE tc.constraint_type = 'FOREIGN KEY'\r\n AND tc.table_schema = $1\r\n AND tc.table_name = $2\r\n GROUP BY tc.constraint_name, ccu.table_schema, ccu.table_name, rc.update_rule, rc.delete_rule\r\n `;\r\n\r\n const result = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return result.rows.map((row) => ({\r\n name: row.constraint_name,\r\n columns: row.column_names,\r\n referencedSchema: row.referenced_schema,\r\n referencedTable: row.referenced_table,\r\n referencedColumns: row.referenced_columns,\r\n onUpdate: row.update_rule,\r\n onDelete: row.delete_rule,\r\n }));\r\n }\r\n\r\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\r\n this.ensureConnected();\r\n\r\n const startTime = Date.now();\r\n try {\r\n const queryConfig: any = {\r\n text: sql,\r\n values: params,\r\n };\r\n\r\n if (timeoutMs) {\r\n queryConfig.statement_timeout = timeoutMs;\r\n }\r\n\r\n const result = await this.pool!.query(queryConfig);\r\n const executionTimeMs = Date.now() - startTime;\r\n\r\n return {\r\n rows: result.rows,\r\n columns: result.fields.map((f: any) => f.name),\r\n rowCount: result.rowCount || 0,\r\n executionTimeMs,\r\n affectedRows: result.rowCount || 0,\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'query');\r\n }\r\n }\r\n\r\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const explainSql = `EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS) ${sql}`;\r\n const result = await this.pool!.query(explainSql, params);\r\n\r\n return {\r\n plan: result.rows[0]['QUERY PLAN'],\r\n formattedPlan: JSON.stringify(result.rows[0]['QUERY PLAN'], null, 2),\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'explain');\r\n }\r\n }\r\n\r\n async testConnection(): Promise<boolean> {\r\n try {\r\n if (!this.pool) return false;\r\n const client = await this.pool.connect();\r\n client.release();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getVersion(): Promise<string> {\r\n this.ensureConnected();\r\n try {\r\n const result = await this.pool!.query('SELECT version()');\r\n return result.rows[0].version;\r\n } catch (error) {\r\n this.handleError(error, 'getVersion');\r\n }\r\n }\r\n}\r\n","import pino from 'pino';\r\n\r\nlet logger: pino.Logger;\r\n\r\nexport function initLogger(level: string = 'info', pretty: boolean = false) {\r\n logger = pino(\r\n {\r\n level,\r\n transport: pretty\r\n ? {\r\n target: 'pino-pretty',\r\n options: {\r\n colorize: true,\r\n translateTime: 'SYS:standard',\r\n ignore: 'pid,hostname',\r\n },\r\n }\r\n : undefined,\r\n },\r\n pino.destination({ dest: 2, sync: false }) // Write to stderr (fd 2) for MCP protocol compatibility\r\n );\r\n \r\n return logger;\r\n}\r\n\r\nexport function getLogger(): pino.Logger {\r\n if (!logger) {\r\n logger = initLogger();\r\n }\r\n return logger;\r\n}\r\n","import {\r\n DatabaseAdapter,\r\n DatabaseConfig,\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n DatabaseError,\r\n} from '../types.js';\r\nimport { getLogger } from '../logger.js';\r\n\r\nexport abstract class BaseAdapter implements DatabaseAdapter {\r\n protected logger = getLogger();\r\n protected connected = false;\r\n\r\n constructor(protected _config: DatabaseConfig) {}\r\n\r\n abstract connect(): Promise<void>;\r\n abstract disconnect(): Promise<void>;\r\n abstract introspect(_options?: IntrospectionOptions): Promise<DatabaseSchema>;\r\n abstract query(_sql: string, _params?: any[], _timeoutMs?: number): Promise<QueryResult>;\r\n abstract explain(_sql: string, _params?: any[]): Promise<ExplainResult>;\r\n abstract testConnection(): Promise<boolean>;\r\n abstract getVersion(): Promise<string>;\r\n\r\n protected ensureConnected(): void {\r\n if (!this.connected) {\r\n throw new DatabaseError(\r\n 'Database not connected',\r\n 'NOT_CONNECTED',\r\n this._config.id\r\n );\r\n }\r\n }\r\n\r\n protected handleError(error: any, operation: string): never {\r\n this.logger.error({ error, dbId: this._config.id, operation }, 'Database operation failed');\r\n throw new DatabaseError(\r\n `${operation} failed: ${error.message}`,\r\n error.code || 'UNKNOWN_ERROR',\r\n this._config.id,\r\n error\r\n );\r\n }\r\n}\r\n","import mysql from 'mysql2/promise';\r\nimport { BaseAdapter } from './base.js';\r\nimport {\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n TableMetadata,\r\n ColumnMetadata,\r\n IndexMetadata,\r\n ForeignKeyMetadata,\r\n SchemaMetadata,\r\n} from '../types.js';\r\nimport { generateSchemaVersion } from '../utils.js';\r\n\r\nexport class MySQLAdapter extends BaseAdapter {\r\n private pool?: mysql.Pool;\r\n private database?: string;\r\n\r\n async connect(): Promise<void> {\r\n try {\r\n this.pool = mysql.createPool({\r\n uri: this._config.url,\r\n waitForConnections: true,\r\n connectionLimit: this._config.pool?.max || 10,\r\n queueLimit: 0,\r\n connectTimeout: this._config.pool?.connectionTimeoutMillis || 10000,\r\n });\r\n\r\n // Test connection and get database name\r\n const connection = await this.pool.getConnection();\r\n const [rows] = await connection.query('SELECT DATABASE() as db');\r\n this.database = (rows as any)[0].db;\r\n connection.release();\r\n\r\n this.connected = true;\r\n this.logger.info({ dbId: this._config.id }, 'MySQL connected');\r\n } catch (error) {\r\n this.handleError(error, 'connect');\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n if (this.pool) {\r\n await this.pool.end();\r\n this.pool = undefined;\r\n this.connected = false;\r\n this.logger.info({ dbId: this._config.id }, 'MySQL disconnected');\r\n }\r\n }\r\n\r\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const schemas = await this.getSchemas(options);\r\n const dbSchema: DatabaseSchema = {\r\n dbId: this._config.id,\r\n dbType: 'mysql',\r\n schemas,\r\n introspectedAt: new Date(),\r\n version: '',\r\n };\r\n\r\n dbSchema.version = generateSchemaVersion(dbSchema);\r\n return dbSchema;\r\n } catch (error) {\r\n this.handleError(error, 'introspect');\r\n }\r\n }\r\n\r\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\r\n // MySQL uses the current database as the schema\r\n const tables = await this.getTables(this.database!, options);\r\n return [\r\n {\r\n name: this.database!,\r\n tables,\r\n },\r\n ];\r\n }\r\n\r\n private async getTables(\r\n schemaName: string,\r\n options?: IntrospectionOptions\r\n ): Promise<TableMetadata[]> {\r\n const result: TableMetadata[] = [];\r\n\r\n let tableTypes = \"'BASE TABLE'\";\r\n if (options?.includeViews) {\r\n tableTypes += \",'VIEW'\";\r\n }\r\n\r\n const tablesQuery = `\r\n SELECT TABLE_NAME, TABLE_TYPE, TABLE_COMMENT\r\n FROM information_schema.TABLES\r\n WHERE TABLE_SCHEMA = ? AND TABLE_TYPE IN (${tableTypes})\r\n ORDER BY TABLE_NAME\r\n ${options?.maxTables ? `LIMIT ${options.maxTables}` : ''}\r\n `;\r\n\r\n const [rows] = await this.pool!.query(tablesQuery, [schemaName]);\r\n\r\n for (const row of rows as any[]) {\r\n const columns = await this.getColumns(schemaName, row.TABLE_NAME);\r\n const indexes = await this.getIndexes(schemaName, row.TABLE_NAME);\r\n const foreignKeys = await this.getForeignKeys(schemaName, row.TABLE_NAME);\r\n\r\n const primaryKey = indexes.find((idx) => idx.isPrimary);\r\n\r\n result.push({\r\n schema: schemaName,\r\n name: row.TABLE_NAME,\r\n type: row.TABLE_TYPE === 'VIEW' ? 'view' : 'table',\r\n columns,\r\n primaryKey,\r\n indexes: indexes.filter((idx) => !idx.isPrimary),\r\n foreignKeys,\r\n comment: row.TABLE_COMMENT,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\r\n const query = `\r\n SELECT\r\n COLUMN_NAME,\r\n DATA_TYPE,\r\n IS_NULLABLE,\r\n COLUMN_DEFAULT,\r\n CHARACTER_MAXIMUM_LENGTH,\r\n NUMERIC_PRECISION,\r\n NUMERIC_SCALE,\r\n EXTRA,\r\n COLUMN_COMMENT\r\n FROM information_schema.COLUMNS\r\n WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\r\n ORDER BY ORDINAL_POSITION\r\n `;\r\n\r\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return (rows as any[]).map((row) => ({\r\n name: row.COLUMN_NAME,\r\n dataType: row.DATA_TYPE,\r\n nullable: row.IS_NULLABLE === 'YES',\r\n defaultValue: row.COLUMN_DEFAULT,\r\n maxLength: row.CHARACTER_MAXIMUM_LENGTH,\r\n precision: row.NUMERIC_PRECISION,\r\n scale: row.NUMERIC_SCALE,\r\n isAutoIncrement: row.EXTRA.includes('auto_increment'),\r\n comment: row.COLUMN_COMMENT,\r\n }));\r\n }\r\n\r\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\r\n const query = `\r\n SELECT\r\n INDEX_NAME,\r\n NON_UNIQUE,\r\n GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS column_names\r\n FROM information_schema.STATISTICS\r\n WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\r\n GROUP BY INDEX_NAME, NON_UNIQUE\r\n `;\r\n\r\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return (rows as any[]).map((row) => ({\r\n name: row.INDEX_NAME,\r\n columns: row.column_names.split(','),\r\n isUnique: row.NON_UNIQUE === 0,\r\n isPrimary: row.INDEX_NAME === 'PRIMARY',\r\n }));\r\n }\r\n\r\n private async getForeignKeys(\r\n schemaName: string,\r\n tableName: string\r\n ): Promise<ForeignKeyMetadata[]> {\r\n const query = `\r\n SELECT\r\n kcu.CONSTRAINT_NAME,\r\n GROUP_CONCAT(kcu.COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS column_names,\r\n kcu.REFERENCED_TABLE_SCHEMA,\r\n kcu.REFERENCED_TABLE_NAME,\r\n GROUP_CONCAT(kcu.REFERENCED_COLUMN_NAME ORDER BY kcu.ORDINAL_POSITION) AS referenced_columns,\r\n rc.UPDATE_RULE,\r\n rc.DELETE_RULE\r\n FROM information_schema.KEY_COLUMN_USAGE AS kcu\r\n JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc\r\n ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\r\n AND kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA\r\n WHERE kcu.TABLE_SCHEMA = ? AND kcu.TABLE_NAME = ?\r\n AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\r\n GROUP BY kcu.CONSTRAINT_NAME, kcu.REFERENCED_TABLE_SCHEMA,\r\n kcu.REFERENCED_TABLE_NAME, rc.UPDATE_RULE, rc.DELETE_RULE\r\n `;\r\n\r\n const [rows] = await this.pool!.query(query, [schemaName, tableName]);\r\n\r\n return (rows as any[]).map((row) => ({\r\n name: row.CONSTRAINT_NAME,\r\n columns: row.column_names.split(','),\r\n referencedSchema: row.REFERENCED_TABLE_SCHEMA,\r\n referencedTable: row.REFERENCED_TABLE_NAME,\r\n referencedColumns: row.referenced_columns.split(','),\r\n onUpdate: row.UPDATE_RULE,\r\n onDelete: row.DELETE_RULE,\r\n }));\r\n }\r\n\r\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\r\n this.ensureConnected();\r\n\r\n const startTime = Date.now();\r\n try {\r\n const connection = await this.pool!.getConnection();\r\n \r\n if (timeoutMs) {\r\n await connection.query(`SET SESSION max_execution_time=${timeoutMs}`);\r\n }\r\n\r\n const [rows, fields] = await connection.query(sql, params);\r\n connection.release();\r\n\r\n const executionTimeMs = Date.now() - startTime;\r\n\r\n return {\r\n rows: Array.isArray(rows) ? rows : [],\r\n columns: Array.isArray(fields) ? fields.map((f: any) => f.name) : [],\r\n rowCount: Array.isArray(rows) ? rows.length : 0,\r\n executionTimeMs,\r\n affectedRows: (rows as any).affectedRows,\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'query');\r\n }\r\n }\r\n\r\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const explainSql = `EXPLAIN FORMAT=JSON ${sql}`;\r\n const [rows] = await this.pool!.query(explainSql, params);\r\n\r\n return {\r\n plan: (rows as any)[0].EXPLAIN,\r\n formattedPlan: JSON.stringify((rows as any)[0].EXPLAIN, null, 2),\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'explain');\r\n }\r\n }\r\n\r\n async testConnection(): Promise<boolean> {\r\n try {\r\n if (!this.pool) return false;\r\n const connection = await this.pool.getConnection();\r\n connection.release();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getVersion(): Promise<string> {\r\n this.ensureConnected();\r\n try {\r\n const [rows] = await this.pool!.query('SELECT VERSION() as version');\r\n return (rows as any)[0].version;\r\n } catch (error) {\r\n this.handleError(error, 'getVersion');\r\n }\r\n }\r\n}\r\n","import Database from 'better-sqlite3';\r\nimport { BaseAdapter } from './base.js';\r\nimport {\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n TableMetadata,\r\n ColumnMetadata,\r\n IndexMetadata,\r\n ForeignKeyMetadata,\r\n SchemaMetadata,\r\n} from '../types.js';\r\nimport { generateSchemaVersion } from '../utils.js';\r\n\r\nexport class SQLiteAdapter extends BaseAdapter {\r\n private db?: Database.Database;\r\n\r\n async connect(): Promise<void> {\r\n try {\r\n const dbPath = this._config.path || this._config.url;\r\n if (!dbPath) {\r\n throw new Error('SQLite requires path or url configuration');\r\n }\r\n\r\n this.db = new Database(dbPath, {\r\n readonly: this._config.readOnly,\r\n fileMustExist: false,\r\n });\r\n\r\n // Enable foreign keys\r\n this.db.pragma('foreign_keys = ON');\r\n\r\n this.connected = true;\r\n this.logger.info({ dbId: this._config.id, path: dbPath }, 'SQLite connected');\r\n } catch (error) {\r\n this.handleError(error, 'connect');\r\n }\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n if (this.db) {\r\n this.db.close();\r\n this.db = undefined;\r\n this.connected = false;\r\n this.logger.info({ dbId: this._config.id }, 'SQLite disconnected');\r\n }\r\n }\r\n\r\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const schemas = await this.getSchemas(options);\r\n const dbSchema: DatabaseSchema = {\r\n dbId: this._config.id,\r\n dbType: 'sqlite',\r\n schemas,\r\n introspectedAt: new Date(),\r\n version: '',\r\n };\r\n\r\n dbSchema.version = generateSchemaVersion(dbSchema);\r\n return dbSchema;\r\n } catch (error) {\r\n this.handleError(error, 'introspect');\r\n }\r\n }\r\n\r\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\r\n const tables = await this.getTables('main', options);\r\n return [\r\n {\r\n name: 'main',\r\n tables,\r\n },\r\n ];\r\n }\r\n\r\n private async getTables(\r\n schemaName: string,\r\n options?: IntrospectionOptions\r\n ): Promise<TableMetadata[]> {\r\n const result: TableMetadata[] = [];\r\n\r\n let query = `\r\n SELECT name, type\r\n FROM sqlite_master\r\n WHERE type IN ('table', 'view')\r\n AND name NOT LIKE 'sqlite_%'\r\n ORDER BY name\r\n `;\r\n\r\n if (options?.maxTables) {\r\n query += ` LIMIT ${options.maxTables}`;\r\n }\r\n\r\n const tables = this.db!.prepare(query).all() as Array<{ name: string; type: string }>;\r\n\r\n for (const table of tables) {\r\n if (table.type === 'view' && !options?.includeViews) {\r\n continue;\r\n }\r\n\r\n const columns = await this.getColumns(table.name);\r\n const indexes = await this.getIndexes(table.name);\r\n const foreignKeys = await this.getForeignKeys(table.name);\r\n\r\n const primaryKey = indexes.find((idx) => idx.isPrimary);\r\n\r\n result.push({\r\n schema: schemaName,\r\n name: table.name,\r\n type: table.type === 'view' ? 'view' : 'table',\r\n columns,\r\n primaryKey,\r\n indexes: indexes.filter((idx) => !idx.isPrimary),\r\n foreignKeys,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getColumns(tableName: string): Promise<ColumnMetadata[]> {\r\n const pragma = this.db!.prepare(`PRAGMA table_info(${tableName})`).all() as Array<{\r\n cid: number;\r\n name: string;\r\n type: string;\r\n notnull: number;\r\n dflt_value: string | null;\r\n pk: number;\r\n }>;\r\n\r\n return pragma.map((col) => ({\r\n name: col.name,\r\n dataType: col.type || 'TEXT',\r\n nullable: col.notnull === 0,\r\n defaultValue: col.dflt_value || undefined,\r\n isAutoIncrement: col.pk === 1 && col.type.toUpperCase() === 'INTEGER',\r\n }));\r\n }\r\n\r\n private async getIndexes(tableName: string): Promise<IndexMetadata[]> {\r\n const result: IndexMetadata[] = [];\r\n\r\n // Get all indexes\r\n const indexes = this.db!.prepare(`PRAGMA index_list(${tableName})`).all() as Array<{\r\n name: string;\r\n unique: number;\r\n origin: string;\r\n }>;\r\n\r\n for (const index of indexes) {\r\n const indexInfo = this.db!.prepare(`PRAGMA index_info(${index.name})`).all() as Array<{\r\n seqno: number;\r\n cid: number;\r\n name: string;\r\n }>;\r\n\r\n result.push({\r\n name: index.name,\r\n columns: indexInfo.map((info) => info.name),\r\n isUnique: index.unique === 1,\r\n isPrimary: index.origin === 'pk',\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getForeignKeys(tableName: string): Promise<ForeignKeyMetadata[]> {\r\n const foreignKeys = this.db!.prepare(`PRAGMA foreign_key_list(${tableName})`).all() as Array<{\r\n id: number;\r\n seq: number;\r\n table: string;\r\n from: string;\r\n to: string;\r\n on_update: string;\r\n on_delete: string;\r\n }>;\r\n\r\n // Group by FK id\r\n const grouped = new Map<number, typeof foreignKeys>();\r\n for (const fk of foreignKeys) {\r\n if (!grouped.has(fk.id)) {\r\n grouped.set(fk.id, []);\r\n }\r\n grouped.get(fk.id)!.push(fk);\r\n }\r\n\r\n return Array.from(grouped.values()).map((fks) => ({\r\n name: `fk_${tableName}_${fks[0].id}`,\r\n columns: fks.map((fk) => fk.from),\r\n referencedSchema: 'main',\r\n referencedTable: fks[0].table,\r\n referencedColumns: fks.map((fk) => fk.to),\r\n onUpdate: fks[0].on_update,\r\n onDelete: fks[0].on_delete,\r\n }));\r\n }\r\n\r\n async query(sql: string, params: any[] = [], timeoutMs?: number): Promise<QueryResult> {\r\n this.ensureConnected();\r\n\r\n const startTime = Date.now();\r\n try {\r\n if (timeoutMs) {\r\n this.db!.pragma(`busy_timeout = ${timeoutMs}`);\r\n }\r\n\r\n const stmt = this.db!.prepare(sql);\r\n const isSelect = sql.trim().toUpperCase().startsWith('SELECT');\r\n\r\n let rows: any[];\r\n let affectedRows = 0;\r\n\r\n if (isSelect) {\r\n rows = stmt.all(...params);\r\n } else {\r\n const result = stmt.run(...params);\r\n rows = [];\r\n affectedRows = result.changes;\r\n }\r\n\r\n const executionTimeMs = Date.now() - startTime;\r\n const columns = rows.length > 0 ? Object.keys(rows[0]) : [];\r\n\r\n return {\r\n rows,\r\n columns,\r\n rowCount: rows.length,\r\n executionTimeMs,\r\n affectedRows,\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'query');\r\n }\r\n }\r\n\r\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const explainSql = `EXPLAIN QUERY PLAN ${sql}`;\r\n const stmt = this.db!.prepare(explainSql);\r\n const plan = stmt.all(...params);\r\n\r\n return {\r\n plan,\r\n formattedPlan: JSON.stringify(plan, null, 2),\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'explain');\r\n }\r\n }\r\n\r\n async testConnection(): Promise<boolean> {\r\n try {\r\n if (!this.db) return false;\r\n this.db.prepare('SELECT 1').get();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getVersion(): Promise<string> {\r\n this.ensureConnected();\r\n try {\r\n const result = this.db!.prepare('SELECT sqlite_version() as version').get() as {\r\n version: string;\r\n };\r\n return `SQLite ${result.version}`;\r\n } catch (error) {\r\n this.handleError(error, 'getVersion');\r\n }\r\n }\r\n}\r\n","import { Connection, Request } from 'tedious';\r\nimport { BaseAdapter } from './base.js';\r\nimport {\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n TableMetadata,\r\n ColumnMetadata,\r\n IndexMetadata,\r\n ForeignKeyMetadata,\r\n SchemaMetadata,\r\n} from '../types.js';\r\nimport { generateSchemaVersion } from '../utils.js';\r\n\r\nexport class MSSQLAdapter extends BaseAdapter {\r\n private connection?: Connection;\r\n\r\n async connect(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n // Parse connection string\r\n const config = this.parseConnectionString(this._config.url!);\r\n\r\n this.connection = new Connection(config);\r\n\r\n this.connection.on('connect', (err) => {\r\n if (err) {\r\n reject(err);\r\n } else {\r\n this.connected = true;\r\n this.logger.info({ dbId: this._config.id }, 'SQL Server connected');\r\n resolve();\r\n }\r\n });\r\n\r\n this.connection.connect();\r\n } catch (error) {\r\n this.handleError(error, 'connect');\r\n }\r\n });\r\n }\r\n\r\n private parseConnectionString(connStr: string): any {\r\n const config: any = {\r\n options: {\r\n encrypt: true,\r\n trustServerCertificate: true,\r\n enableArithAbort: true,\r\n },\r\n };\r\n\r\n // Simple parser for SQL Server connection strings\r\n const parts = connStr.split(';').filter((p) => p.trim());\r\n for (const part of parts) {\r\n const [key, value] = part.split('=').map((s) => s.trim());\r\n const lowerKey = key.toLowerCase();\r\n\r\n if (lowerKey === 'server') {\r\n const [host, port] = value.split(',');\r\n config.server = host;\r\n if (port) config.options.port = parseInt(port);\r\n } else if (lowerKey === 'database') {\r\n config.options.database = value;\r\n } else if (lowerKey === 'user id') {\r\n config.authentication = {\r\n type: 'default',\r\n options: { userName: value, password: '' },\r\n };\r\n } else if (lowerKey === 'password') {\r\n if (config.authentication) {\r\n config.authentication.options.password = value;\r\n }\r\n } else if (lowerKey === 'encrypt') {\r\n config.options.encrypt = value.toLowerCase() === 'true';\r\n } else if (lowerKey === 'trustservercertificate') {\r\n config.options.trustServerCertificate = value.toLowerCase() === 'true';\r\n }\r\n }\r\n\r\n return config;\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n if (this.connection) {\r\n this.connection.close();\r\n this.connection = undefined;\r\n this.connected = false;\r\n this.logger.info({ dbId: this._config.id }, 'SQL Server disconnected');\r\n }\r\n }\r\n\r\n private executeQuery(sql: string, _params: any[] = []): Promise<any[]> {\r\n return new Promise((resolve, reject) => {\r\n const rows: any[] = [];\r\n const request = new Request(sql, (err) => {\r\n if (err) {\r\n reject(err);\r\n } else {\r\n resolve(rows);\r\n }\r\n });\r\n\r\n request.on('row', (columns) => {\r\n const row: any = {};\r\n columns.forEach((col: any) => {\r\n row[col.metadata.colName] = col.value;\r\n });\r\n rows.push(row);\r\n });\r\n\r\n this.connection!.execSql(request);\r\n });\r\n }\r\n\r\n async introspect(options?: IntrospectionOptions): Promise<DatabaseSchema> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const schemas = await this.getSchemas(options);\r\n const dbSchema: DatabaseSchema = {\r\n dbId: this._config.id,\r\n dbType: 'mssql',\r\n schemas,\r\n introspectedAt: new Date(),\r\n version: '',\r\n };\r\n\r\n dbSchema.version = generateSchemaVersion(dbSchema);\r\n return dbSchema;\r\n } catch (error) {\r\n this.handleError(error, 'introspect');\r\n }\r\n }\r\n\r\n private async getSchemas(options?: IntrospectionOptions): Promise<SchemaMetadata[]> {\r\n const result: SchemaMetadata[] = [];\r\n\r\n const schemasQuery = `\r\n SELECT SCHEMA_NAME\r\n FROM INFORMATION_SCHEMA.SCHEMATA\r\n WHERE SCHEMA_NAME NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\r\n ORDER BY SCHEMA_NAME\r\n `;\r\n\r\n const schemasResult = await this.executeQuery(schemasQuery);\r\n let schemaNames = schemasResult.map((r) => r.SCHEMA_NAME);\r\n\r\n if (options?.includeSchemas && options.includeSchemas.length > 0) {\r\n schemaNames = schemaNames.filter((s) => options.includeSchemas!.includes(s));\r\n }\r\n if (options?.excludeSchemas && options.excludeSchemas.length > 0) {\r\n schemaNames = schemaNames.filter((s) => !options.excludeSchemas!.includes(s));\r\n }\r\n\r\n for (const schemaName of schemaNames) {\r\n const tables = await this.getTables(schemaName, options);\r\n result.push({\r\n name: schemaName,\r\n tables,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getTables(\r\n schemaName: string,\r\n options?: IntrospectionOptions\r\n ): Promise<TableMetadata[]> {\r\n const result: TableMetadata[] = [];\r\n\r\n let tableTypes = \"'BASE TABLE'\";\r\n if (options?.includeViews) {\r\n tableTypes += \",'VIEW'\";\r\n }\r\n\r\n const tablesQuery = `\r\n SELECT TABLE_NAME, TABLE_TYPE\r\n FROM INFORMATION_SCHEMA.TABLES\r\n WHERE TABLE_SCHEMA = '${schemaName}' AND TABLE_TYPE IN (${tableTypes})\r\n ORDER BY TABLE_NAME\r\n ${options?.maxTables ? `OFFSET 0 ROWS FETCH NEXT ${options.maxTables} ROWS ONLY` : ''}\r\n `;\r\n\r\n const tablesResult = await this.executeQuery(tablesQuery);\r\n\r\n for (const row of tablesResult) {\r\n const columns = await this.getColumns(schemaName, row.TABLE_NAME);\r\n const indexes = await this.getIndexes(schemaName, row.TABLE_NAME);\r\n const foreignKeys = await this.getForeignKeys(schemaName, row.TABLE_NAME);\r\n\r\n const primaryKey = indexes.find((idx) => idx.isPrimary);\r\n\r\n result.push({\r\n schema: schemaName,\r\n name: row.TABLE_NAME,\r\n type: row.TABLE_TYPE === 'VIEW' ? 'view' : 'table',\r\n columns,\r\n primaryKey,\r\n indexes: indexes.filter((idx) => !idx.isPrimary),\r\n foreignKeys,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async getColumns(schemaName: string, tableName: string): Promise<ColumnMetadata[]> {\r\n const query = `\r\n SELECT\r\n COLUMN_NAME,\r\n DATA_TYPE,\r\n IS_NULLABLE,\r\n COLUMN_DEFAULT,\r\n CHARACTER_MAXIMUM_LENGTH,\r\n NUMERIC_PRECISION,\r\n NUMERIC_SCALE,\r\n COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'IsIdentity') AS IS_IDENTITY\r\n FROM INFORMATION_SCHEMA.COLUMNS\r\n WHERE TABLE_SCHEMA = '${schemaName}' AND TABLE_NAME = '${tableName}'\r\n ORDER BY ORDINAL_POSITION\r\n `;\r\n\r\n const result = await this.executeQuery(query);\r\n\r\n return result.map((row) => ({\r\n name: row.COLUMN_NAME,\r\n dataType: row.DATA_TYPE,\r\n nullable: row.IS_NULLABLE === 'YES',\r\n defaultValue: row.COLUMN_DEFAULT,\r\n maxLength: row.CHARACTER_MAXIMUM_LENGTH,\r\n precision: row.NUMERIC_PRECISION,\r\n scale: row.NUMERIC_SCALE,\r\n isAutoIncrement: row.IS_IDENTITY === 1,\r\n }));\r\n }\r\n\r\n private async getIndexes(schemaName: string, tableName: string): Promise<IndexMetadata[]> {\r\n const query = `\r\n SELECT\r\n i.name AS index_name,\r\n i.is_unique,\r\n i.is_primary_key,\r\n STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY ic.key_ordinal) AS column_names\r\n FROM sys.indexes i\r\n INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\r\n INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\r\n INNER JOIN sys.tables t ON i.object_id = t.object_id\r\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\r\n WHERE s.name = '${schemaName}' AND t.name = '${tableName}'\r\n GROUP BY i.name, i.is_unique, i.is_primary_key\r\n `;\r\n\r\n const result = await this.executeQuery(query);\r\n\r\n return result.map((row) => ({\r\n name: row.index_name,\r\n columns: row.column_names.split(','),\r\n isUnique: row.is_unique,\r\n isPrimary: row.is_primary_key,\r\n }));\r\n }\r\n\r\n private async getForeignKeys(\r\n schemaName: string,\r\n tableName: string\r\n ): Promise<ForeignKeyMetadata[]> {\r\n const query = `\r\n SELECT\r\n fk.name AS constraint_name,\r\n STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY fkc.constraint_column_id) AS column_names,\r\n rs.name AS referenced_schema,\r\n rt.name AS referenced_table,\r\n STRING_AGG(rc.name, ',') WITHIN GROUP (ORDER BY fkc.constraint_column_id) AS referenced_columns,\r\n fk.update_referential_action_desc,\r\n fk.delete_referential_action_desc\r\n FROM sys.foreign_keys fk\r\n INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\r\n INNER JOIN sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id\r\n INNER JOIN sys.columns rc ON fkc.referenced_object_id = rc.object_id AND fkc.referenced_column_id = rc.column_id\r\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\r\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\r\n INNER JOIN sys.tables rt ON fk.referenced_object_id = rt.object_id\r\n INNER JOIN sys.schemas rs ON rt.schema_id = rs.schema_id\r\n WHERE s.name = '${schemaName}' AND t.name = '${tableName}'\r\n GROUP BY fk.name, rs.name, rt.name, fk.update_referential_action_desc, fk.delete_referential_action_desc\r\n `;\r\n\r\n const result = await this.executeQuery(query);\r\n\r\n return result.map((row) => ({\r\n name: row.constraint_name,\r\n columns: row.column_names.split(','),\r\n referencedSchema: row.referenced_schema,\r\n referencedTable: row.referenced_table,\r\n referencedColumns: row.referenced_columns.split(','),\r\n onUpdate: row.update_referential_action_desc,\r\n onDelete: row.delete_referential_action_desc,\r\n }));\r\n }\r\n\r\n async query(sql: string, params: any[] = [], _timeoutMs?: number): Promise<QueryResult> {\r\n this.ensureConnected();\r\n\r\n const startTime = Date.now();\r\n try {\r\n const rows = await this.executeQuery(sql, params);\r\n const executionTimeMs = Date.now() - startTime;\r\n const columns = rows.length > 0 ? Object.keys(rows[0]) : [];\r\n\r\n return {\r\n rows,\r\n columns,\r\n rowCount: rows.length,\r\n executionTimeMs,\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'query');\r\n }\r\n }\r\n\r\n async explain(sql: string, params: any[] = []): Promise<ExplainResult> {\r\n this.ensureConnected();\r\n\r\n try {\r\n const explainSql = `SET SHOWPLAN_TEXT ON; ${sql}; SET SHOWPLAN_TEXT OFF;`;\r\n const plan = await this.executeQuery(explainSql, params);\r\n\r\n return {\r\n plan,\r\n formattedPlan: JSON.stringify(plan, null, 2),\r\n };\r\n } catch (error) {\r\n this.handleError(error, 'explain');\r\n }\r\n }\r\n\r\n async testConnection(): Promise<boolean> {\r\n try {\r\n if (!this.connection) return false;\r\n await this.executeQuery('SELECT 1');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getVersion(): Promise<string> {\r\n this.ensureConnected();\r\n try {\r\n const result = await this.executeQuery('SELECT @@VERSION as version');\r\n return result[0].version;\r\n } catch (error) {\r\n this.handleError(error, 'getVersion');\r\n }\r\n }\r\n}\r\n","import { BaseAdapter } from './base.js';\r\nimport {\r\n DatabaseSchema,\r\n QueryResult,\r\n ExplainResult,\r\n IntrospectionOptions,\r\n} from '../types.js';\r\n\r\n/**\r\n * Oracle adapter stub - requires Oracle Instant Client to be installed\r\n * TODO: Implement full Oracle support when environment supports it\r\n * \r\n * To use Oracle:\r\n * 1. Install Oracle Instant Client\r\n * 2. Set LD_LIBRARY_PATH (Linux) or PATH (Windows) to include Instant Client\r\n * 3. Install oracledb package: npm install oracledb\r\n * 4. Implement the methods below using oracledb\r\n */\r\nexport class OracleAdapter extends BaseAdapter {\r\n private connection?: any;\r\n\r\n async connect(): Promise<void> {\r\n this.logger.warn(\r\n { dbId: this._config.id },\r\n 'Oracle adapter is not fully implemented. Requires Oracle Instant Client and oracledb package.'\r\n );\r\n \r\n // TODO: Implement Oracle connection\r\n // Example:\r\n // const oracledb = require('oracledb');\r\n // this.connection = await oracledb.getConnection({\r\n // user: config.user,\r\n // password: config.password,\r\n // connectString: config.connectString,\r\n // poolMin: this._config.pool?.min || 2,\r\n // poolMax: this._config.pool?.max || 10,\r\n // });\r\n \r\n throw new Error(\r\n 'Oracle adapter not implemented. Please install Oracle Instant Client and implement OracleAdapter methods.'\r\n );\r\n }\r\n\r\n async disconnect(): Promise<void> {\r\n // TODO: Implement Oracle disconnect\r\n if (this.connection) {\r\n // await this.connection.close();\r\n this.connection = undefined;\r\n this.connected = false;\r\n }\r\n }\r\n\r\n async introspect(_options?: IntrospectionOptions): Promise<DatabaseSchema> {\r\n this.ensureConnected();\r\n\r\n // TODO: Implement Oracle introspection\r\n // Query ALL_TABLES, ALL_TAB_COLUMNS, ALL_CONSTRAINTS, etc.\r\n throw new Error('Oracle introspection not implemented');\r\n }\r\n\r\n async query(_sql: string, _params: any[] = [], _timeoutMs?: number): Promise<QueryResult> {\r\n this.ensureConnected();\r\n\r\n // TODO: Implement Oracle query execution\r\n throw new Error('Oracle query not implemented');\r\n }\r\n\r\n async explain(_sql: string, _params: any[] = []): Promise<ExplainResult> {\r\n this.ensureConnected();\r\n\r\n // TODO: Implement Oracle EXPLAIN PLAN\r\n // Use: EXPLAIN PLAN FOR ... then SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)\r\n throw new Error('Oracle explain not implemented');\r\n }\r\n\r\n async testConnection(): Promise<boolean> {\r\n // TODO: Implement connection test\r\n return false;\r\n }\r\n\r\n async getVersion(): Promise<string> {\r\n // TODO: Query v$version or SELECT * FROM v$version\r\n return 'Oracle (not implemented)';\r\n }\r\n}\r\n","import { DatabaseAdapter, DatabaseConfig } from '../types.js';\r\nimport { PostgresAdapter } from './postgres.js';\r\nimport { MySQLAdapter } from './mysql.js';\r\nimport { SQLiteAdapter } from './sqlite.js';\r\nimport { MSSQLAdapter } from './mssql.js';\r\nimport { OracleAdapter } from './oracle.js';\r\n\r\nexport function createAdapter(config: DatabaseConfig): DatabaseAdapter {\r\n switch (config.type) {\r\n case 'postgres':\r\n return new PostgresAdapter(config);\r\n case 'mysql':\r\n return new MySQLAdapter(config);\r\n case 'sqlite':\r\n return new SQLiteAdapter(config);\r\n case 'mssql':\r\n return new MSSQLAdapter(config);\r\n case 'oracle':\r\n return new OracleAdapter(config);\r\n default:\r\n throw new Error(`Unsupported database type: ${config.type}`);\r\n }\r\n}\r\n\r\nexport { PostgresAdapter, MySQLAdapter, SQLiteAdapter, MSSQLAdapter, OracleAdapter };\r\n","import fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { DatabaseSchema, Relationship, CacheError } from './types.js';\r\nimport { inferRelationships } from './utils.js';\r\nimport { getLogger } from './logger.js';\r\n\r\nexport interface CacheEntry {\r\n schema: DatabaseSchema;\r\n relationships: Relationship[];\r\n cachedAt: Date;\r\n ttlMinutes: number;\r\n}\r\n\r\nexport interface CacheStatus {\r\n dbId: string;\r\n exists: boolean;\r\n age?: number; // milliseconds\r\n ttlMinutes?: number;\r\n expired?: boolean;\r\n version?: string;\r\n tableCount?: number;\r\n relationshipCount?: number;\r\n}\r\n\r\nexport class SchemaCache {\r\n private logger = getLogger();\r\n private cache = new Map<string, CacheEntry>();\r\n private introspectionLocks = new Map<string, Promise<void>>();\r\n\r\n constructor(\r\n private _cacheDir: string,\r\n private _defaultTtlMinutes: number\r\n ) {}\r\n\r\n async init(): Promise<void> {\r\n try {\r\n await fs.mkdir(this._cacheDir, { recursive: true });\r\n this.logger.info({ cacheDir: this._cacheDir }, 'Schema cache initialized');\r\n } catch (error: any) {\r\n throw new CacheError('Failed to initialize cache directory', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get cached schema if valid, otherwise return null\r\n */\r\n async get(dbId: string): Promise<CacheEntry | null> {\r\n // Check memory cache first\r\n const memEntry = this.cache.get(dbId);\r\n if (memEntry && !this.isExpired(memEntry)) {\r\n return memEntry;\r\n }\r\n\r\n // Try to load from disk\r\n try {\r\n const diskEntry = await this.loadFromDisk(dbId);\r\n if (diskEntry && !this.isExpired(diskEntry)) {\r\n this.cache.set(dbId, diskEntry);\r\n return diskEntry;\r\n }\r\n } catch (error) {\r\n this.logger.warn({ dbId, error }, 'Failed to load cache from disk');\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Set or update cache entry\r\n */\r\n async set(dbId: string, schema: DatabaseSchema, ttlMinutes?: number): Promise<void> {\r\n const entry: CacheEntry = {\r\n schema,\r\n relationships: this.buildRelationships(schema),\r\n cachedAt: new Date(),\r\n ttlMinutes: ttlMinutes || this._defaultTtlMinutes,\r\n };\r\n\r\n this.cache.set(dbId, entry);\r\n\r\n // Persist to disk asynchronously\r\n this.saveToDisk(dbId, entry).catch((error) => {\r\n this.logger.error({ dbId, error }, 'Failed to save cache to disk');\r\n });\r\n }\r\n\r\n /**\r\n * Clear cache for a specific database or all databases\r\n */\r\n async clear(dbId?: string): Promise<void> {\r\n if (dbId) {\r\n this.cache.delete(dbId);\r\n try {\r\n const filePath = this.getCacheFilePath(dbId);\r\n await fs.unlink(filePath);\r\n } catch (error: any) {\r\n if (error.code !== 'ENOENT') {\r\n this.logger.warn({ dbId, error }, 'Failed to delete cache file');\r\n }\r\n }\r\n this.logger.info({ dbId }, 'Cache cleared');\r\n } else {\r\n this.cache.clear();\r\n try {\r\n const files = await fs.readdir(this._cacheDir);\r\n await Promise.all(\r\n files\r\n .filter((f) => f.endsWith('.json'))\r\n .map((f) => fs.unlink(path.join(this._cacheDir, f)))\r\n );\r\n } catch (error) {\r\n this.logger.warn({ error }, 'Failed to clear cache directory');\r\n }\r\n this.logger.info('All caches cleared');\r\n }\r\n }\r\n\r\n /**\r\n * Get cache status\r\n */\r\n async getStatus(dbId?: string): Promise<CacheStatus[]> {\r\n const statuses: CacheStatus[] = [];\r\n\r\n if (dbId) {\r\n const status = await this.getStatusForDb(dbId);\r\n statuses.push(status);\r\n } else {\r\n // Get status for all cached databases\r\n const dbIds = new Set([\r\n ...this.cache.keys(),\r\n ...(await this.getPersistedDbIds()),\r\n ]);\r\n\r\n for (const id of dbIds) {\r\n const status = await this.getStatusForDb(id);\r\n statuses.push(status);\r\n }\r\n }\r\n\r\n return statuses;\r\n }\r\n\r\n private async getStatusForDb(dbId: string): Promise<CacheStatus> {\r\n const entry = await this.get(dbId);\r\n\r\n if (!entry) {\r\n return {\r\n dbId,\r\n exists: false,\r\n };\r\n }\r\n\r\n const age = Date.now() - new Date(entry.cachedAt).getTime();\r\n const expired = this.isExpired(entry);\r\n\r\n return {\r\n dbId,\r\n exists: true,\r\n age,\r\n ttlMinutes: entry.ttlMinutes,\r\n expired,\r\n version: entry.schema.version,\r\n tableCount: entry.schema.schemas.reduce((sum, s) => sum + s.tables.length, 0),\r\n relationshipCount: entry.relationships.length,\r\n };\r\n }\r\n\r\n /**\r\n * Acquire lock for introspection to prevent concurrent introspection\r\n */\r\n async acquireIntrospectionLock(dbId: string): Promise<() => void> {\r\n // Wait for existing introspection to complete\r\n const existingLock = this.introspectionLocks.get(dbId);\r\n if (existingLock) {\r\n await existingLock;\r\n }\r\n\r\n // Create new lock\r\n let releaseLock: () => void;\r\n const lockPromise = new Promise<void>((resolve) => {\r\n releaseLock = resolve;\r\n });\r\n\r\n this.introspectionLocks.set(dbId, lockPromise);\r\n\r\n return () => {\r\n releaseLock!();\r\n this.introspectionLocks.delete(dbId);\r\n };\r\n }\r\n\r\n private isExpired(entry: CacheEntry): boolean {\r\n const age = Date.now() - new Date(entry.cachedAt).getTime();\r\n const ttlMs = entry.ttlMinutes * 60 * 1000;\r\n return age > ttlMs;\r\n }\r\n\r\n private buildRelationships(schema: DatabaseSchema): Relationship[] {\r\n const relationships: Relationship[] = [];\r\n\r\n // Collect explicit foreign key relationships\r\n for (const schemaObj of schema.schemas) {\r\n for (const table of schemaObj.tables) {\r\n for (const fk of table.foreignKeys) {\r\n relationships.push({\r\n fromSchema: schemaObj.name,\r\n fromTable: table.name,\r\n fromColumns: fk.columns,\r\n toSchema: fk.referencedSchema,\r\n toTable: fk.referencedTable,\r\n toColumns: fk.referencedColumns,\r\n type: 'foreign_key',\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Infer additional relationships\r\n const inferred = inferRelationships(schema);\r\n \r\n // Avoid duplicates\r\n const relationshipKeys = new Set(\r\n relationships.map((r) => this.getRelationshipKey(r))\r\n );\r\n \r\n for (const rel of inferred) {\r\n const key = this.getRelationshipKey(rel);\r\n if (!relationshipKeys.has(key)) {\r\n relationships.push(rel);\r\n relationshipKeys.add(key);\r\n }\r\n }\r\n\r\n return relationships;\r\n }\r\n\r\n private getRelationshipKey(rel: Relationship): string {\r\n return `${rel.fromSchema}.${rel.fromTable}.${rel.fromColumns.join(',')}→${rel.toSchema}.${rel.toTable}.${rel.toColumns.join(',')}`;\r\n }\r\n\r\n private getCacheFilePath(dbId: string): string {\r\n return path.join(this._cacheDir, `${dbId}.json`);\r\n }\r\n\r\n private async loadFromDisk(dbId: string): Promise<CacheEntry | null> {\r\n try {\r\n const filePath = this.getCacheFilePath(dbId);\r\n const data = await fs.readFile(filePath, 'utf-8');\r\n const entry = JSON.parse(data);\r\n \r\n // Convert date strings back to Date objects\r\n entry.cachedAt = new Date(entry.cachedAt);\r\n entry.schema.introspectedAt = new Date(entry.schema.introspectedAt);\r\n \r\n return entry;\r\n } catch (error: any) {\r\n if (error.code === 'ENOENT') {\r\n return null;\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n private async saveToDisk(dbId: string, entry: CacheEntry): Promise<void> {\r\n const filePath = this.getCacheFilePath(dbId);\r\n const data = JSON.stringify(entry, null, 2);\r\n await fs.writeFile(filePath, data, 'utf-8');\r\n }\r\n\r\n private async getPersistedDbIds(): Promise<string[]> {\r\n try {\r\n const files = await fs.readdir(this._cacheDir);\r\n return files\r\n .filter((f) => f.endsWith('.json'))\r\n .map((f) => f.replace('.json', ''));\r\n } catch {\r\n return [];\r\n }\r\n }\r\n}\r\n","import {\r\n QueryHistoryEntry,\r\n QueryComplexity,\r\n IndexRecommendation,\r\n QueryPerformanceProfile,\r\n PerformanceBottleneck,\r\n PerformanceRecommendation,\r\n SlowQueryAlert,\r\n QueryOptimizationResult,\r\n DatabaseSchema,\r\n ExplainResult\r\n} from './types.js';\r\nimport { extractTableNames } from './utils.js';\r\n\r\nexport interface QueryOptimizerOptions {\r\n slowQueryThresholdMs: number;\r\n maxHistoryForAnalysis: number;\r\n enableAutoAnalysis: boolean;\r\n}\r\n\r\nexport class QueryOptimizer {\r\n private slowQueryThresholdMs: number;\r\n private slowQueryAlerts = new Map<string, SlowQueryAlert[]>();\r\n\r\n constructor(options: QueryOptimizerOptions = {\r\n slowQueryThresholdMs: 1000,\r\n maxHistoryForAnalysis: 1000,\r\n enableAutoAnalysis: true\r\n }) {\r\n this.slowQueryThresholdMs = options.slowQueryThresholdMs;\r\n }\r\n\r\n /**\r\n * Analyze query complexity and extract performance metrics\r\n */\r\n analyzeQueryComplexity(sql: string): QueryComplexity {\r\n const complexity: QueryComplexity = {\r\n selectColumns: this.countSelectColumns(sql),\r\n whereConditions: this.countWhereConditions(sql),\r\n joinCount: this.countJoins(sql),\r\n subqueryCount: this.countSubqueries(sql),\r\n hasAggregations: /\\b(COUNT|SUM|AVG|MIN|MAX)\\s*\\(/i.test(sql),\r\n hasDistinct: /\\bDISTINCT\\b/i.test(sql),\r\n hasOrderBy: /\\bORDER\\s+BY\\b/i.test(sql),\r\n hasGroupBy: /\\bGROUP\\s+BY\\b/i.test(sql),\r\n estimatedComplexity: 'simple'\r\n };\r\n\r\n // Calculate complexity score\r\n let score = 0;\r\n score += complexity.selectColumns * 0.5;\r\n score += complexity.whereConditions * 1;\r\n score += complexity.joinCount * 2;\r\n score += complexity.subqueryCount * 3;\r\n score += complexity.hasAggregations ? 2 : 0;\r\n score += complexity.hasDistinct ? 1 : 0;\r\n score += complexity.hasOrderBy ? 1 : 0;\r\n score += complexity.hasGroupBy ? 1 : 0;\r\n\r\n if (score <= 3) complexity.estimatedComplexity = 'simple';\r\n else if (score <= 7) complexity.estimatedComplexity = 'medium';\r\n else if (score <= 12) complexity.estimatedComplexity = 'complex';\r\n else complexity.estimatedComplexity = 'very_complex';\r\n\r\n return complexity;\r\n }\r\n\r\n /**\r\n * Generate index recommendations based on query history and schema\r\n */\r\n generateIndexRecommendations(\r\n queryHistory: QueryHistoryEntry[],\r\n schema: DatabaseSchema\r\n ): IndexRecommendation[] {\r\n const recommendations: IndexRecommendation[] = [];\r\n const columnUsage = new Map<string, { table: string; usage: number; inWhere: boolean; inJoin: boolean }>();\r\n\r\n // Analyze query patterns\r\n for (const entry of queryHistory) {\r\n if (entry.error) continue;\r\n\r\n const tables = entry.tables;\r\n\r\n // Extract WHERE conditions\r\n const whereMatch = entry.sql.match(/WHERE\\s+(.+?)(?:\\s+(GROUP|ORDER|LIMIT|$))/i);\r\n if (whereMatch) {\r\n const whereClause = whereMatch[1];\r\n const columns = this.extractColumnsFromCondition(whereClause, tables, schema);\r\n for (const col of columns) {\r\n const key = `${col.table}.${col.column}`;\r\n const existing = columnUsage.get(key) || { table: col.table, usage: 0, inWhere: false, inJoin: false };\r\n existing.usage++;\r\n existing.inWhere = true;\r\n columnUsage.set(key, existing);\r\n }\r\n }\r\n\r\n // Extract JOIN conditions\r\n const joinMatches = entry.sql.match(/JOIN\\s+\\w+\\s+ON\\s+(.+?)(?:\\s+(WHERE|GROUP|ORDER|LIMIT|$))/gi);\r\n if (joinMatches) {\r\n for (const joinMatch of joinMatches) {\r\n const joinClause = joinMatch.replace(/JOIN\\s+\\w+\\s+ON\\s+/i, '');\r\n const columns = this.extractColumnsFromCondition(joinClause, tables, schema);\r\n for (const col of columns) {\r\n const key = `${col.table}.${col.column}`;\r\n const existing = columnUsage.get(key) || { table: col.table, usage: 0, inWhere: false, inJoin: false };\r\n existing.usage++;\r\n existing.inJoin = true;\r\n columnUsage.set(key, existing);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Generate recommendations\r\n for (const [key, usage] of columnUsage) {\r\n if (usage.usage < 3) continue; // Need minimum usage\r\n\r\n const [tableName, columnName] = key.split('.');\r\n const table = this.findTableInSchema(schema, tableName);\r\n if (!table) continue;\r\n\r\n // Check if index already exists\r\n const existingIndex = table.indexes.find(idx =>\r\n idx.columns.includes(columnName) && !idx.isPrimary\r\n );\r\n\r\n if (existingIndex) continue;\r\n\r\n const recommendation: IndexRecommendation = {\r\n table: tableName,\r\n columns: [columnName],\r\n type: 'single',\r\n reason: `Column ${columnName} is frequently used in ${usage.inWhere ? 'WHERE' : ''}${usage.inWhere && usage.inJoin ? ' and ' : ''}${usage.inJoin ? 'JOIN' : ''} conditions`,\r\n impact: usage.usage > 10 ? 'high' : usage.usage > 5 ? 'medium' : 'low'\r\n };\r\n\r\n recommendations.push(recommendation);\r\n }\r\n\r\n // Sort by impact and usage\r\n return recommendations.sort((a, b) => {\r\n const impactOrder = { high: 3, medium: 2, low: 1 };\r\n return impactOrder[b.impact] - impactOrder[a.impact];\r\n });\r\n }\r\n\r\n /**\r\n * Profile query performance using EXPLAIN plan\r\n */\r\n async profileQueryPerformance(\r\n _dbId: string,\r\n sql: string,\r\n explainResult: ExplainResult,\r\n executionTimeMs: number,\r\n rowCount: number\r\n ): Promise<QueryPerformanceProfile> {\r\n const bottlenecks: PerformanceBottleneck[] = [];\r\n const recommendations: PerformanceRecommendation[] = [];\r\n\r\n // Analyze EXPLAIN plan for bottlenecks\r\n if (explainResult.plan) {\r\n bottlenecks.push(...this.analyzeExplainPlan(explainResult.plan));\r\n }\r\n\r\n // Time-based analysis\r\n if (executionTimeMs > this.slowQueryThresholdMs) {\r\n bottlenecks.push({\r\n type: 'table_scan',\r\n severity: executionTimeMs > this.slowQueryThresholdMs * 5 ? 'critical' : 'high',\r\n description: `Query execution time (${executionTimeMs}ms) exceeds threshold (${this.slowQueryThresholdMs}ms)`,\r\n estimatedCost: executionTimeMs\r\n });\r\n }\r\n\r\n // Generate recommendations based on bottlenecks\r\n for (const bottleneck of bottlenecks) {\r\n switch (bottleneck.type) {\r\n case 'table_scan':\r\n recommendations.push({\r\n type: 'add_index',\r\n description: `Consider adding an index on ${bottleneck.table || 'frequently queried columns'}`,\r\n impact: 'high',\r\n effort: 'medium'\r\n });\r\n break;\r\n case 'join':\r\n recommendations.push({\r\n type: 'optimize_join',\r\n description: 'Review JOIN conditions and ensure proper indexing on join columns',\r\n impact: 'high',\r\n effort: 'medium'\r\n });\r\n break;\r\n case 'sort':\r\n recommendations.push({\r\n type: 'add_index',\r\n description: 'Consider adding an index to avoid sorting operations',\r\n impact: 'medium',\r\n effort: 'medium'\r\n });\r\n break;\r\n }\r\n }\r\n\r\n // Calculate overall performance score (0-100)\r\n let score = 100;\r\n for (const bottleneck of bottlenecks) {\r\n const severityPenalty = { critical: 30, high: 20, medium: 10, low: 5 };\r\n score -= severityPenalty[bottleneck.severity];\r\n }\r\n score = Math.max(0, Math.min(100, score));\r\n\r\n return {\r\n queryId: this.generateQueryId(sql),\r\n sql,\r\n executionTimeMs,\r\n rowCount,\r\n bottlenecks,\r\n recommendations,\r\n overallScore: score\r\n };\r\n }\r\n\r\n /**\r\n * Detect and alert on slow queries\r\n */\r\n detectSlowQueries(queryHistory: QueryHistoryEntry[], dbId: string): SlowQueryAlert[] {\r\n for (const entry of queryHistory) {\r\n if (entry.executionTimeMs > this.slowQueryThresholdMs) {\r\n const queryId = this.generateQueryId(entry.sql);\r\n const existingAlerts = this.slowQueryAlerts.get(dbId) || [];\r\n const existingAlert = existingAlerts.find(a => a.queryId === queryId);\r\n\r\n if (existingAlert) {\r\n existingAlert.frequency++;\r\n existingAlert.timestamp = entry.timestamp;\r\n if (entry.executionTimeMs > existingAlert.executionTimeMs) {\r\n existingAlert.executionTimeMs = entry.executionTimeMs;\r\n }\r\n } else {\r\n const alert: SlowQueryAlert = {\r\n dbId,\r\n queryId,\r\n sql: entry.sql,\r\n executionTimeMs: entry.executionTimeMs,\r\n thresholdMs: this.slowQueryThresholdMs,\r\n timestamp: entry.timestamp,\r\n frequency: 1,\r\n recommendations: []\r\n };\r\n existingAlerts.push(alert);\r\n }\r\n\r\n this.slowQueryAlerts.set(dbId, existingAlerts);\r\n }\r\n }\r\n\r\n return this.slowQueryAlerts.get(dbId) || [];\r\n }\r\n\r\n /**\r\n * Suggest optimized versions of queries\r\n */\r\n suggestQueryRewrites(sql: string, schema: DatabaseSchema): QueryOptimizationResult {\r\n const optimizations: string[] = [];\r\n let optimizedQuery = sql;\r\n let performanceGain = 0;\r\n\r\n // Remove unnecessary DISTINCT\r\n if (/\\bDISTINCT\\b/i.test(sql) && this.canRemoveDistinct(sql, schema)) {\r\n optimizedQuery = optimizedQuery.replace(/\\bDISTINCT\\b/i, '');\r\n optimizations.push('Removed unnecessary DISTINCT clause');\r\n performanceGain += 15;\r\n }\r\n\r\n // Suggest LIMIT for queries without it\r\n if (!/\\bLIMIT\\b/i.test(sql) && !/\\bCOUNT\\b/i.test(sql)) {\r\n optimizedQuery += ' LIMIT 1000';\r\n optimizations.push('Added LIMIT clause to prevent large result sets');\r\n performanceGain += 10;\r\n }\r\n\r\n // Check for SELECT *\r\n if (/\\bSELECT\\s+\\*\\s+FROM\\b/i.test(sql)) {\r\n optimizations.push('Consider selecting only required columns instead of SELECT *');\r\n performanceGain += 5;\r\n }\r\n\r\n // Check for missing WHERE clauses on large tables\r\n const tables = extractTableNames(sql);\r\n for (const table of tables) {\r\n const tableMeta = this.findTableInSchema(schema, table);\r\n if (tableMeta && !/\\bWHERE\\b/i.test(sql)) {\r\n optimizations.push(`Consider adding WHERE clause for table ${table} to reduce data scanned`);\r\n performanceGain += 20;\r\n }\r\n }\r\n\r\n return {\r\n originalQuery: sql,\r\n optimizedQuery,\r\n improvements: optimizations,\r\n performanceGain: Math.min(100, performanceGain),\r\n confidence: optimizations.length > 2 ? 'high' : optimizations.length > 0 ? 'medium' : 'low'\r\n };\r\n }\r\n\r\n /**\r\n * Get performance analytics across all queries\r\n */\r\n getPerformanceAnalytics(queryHistory: QueryHistoryEntry[]) {\r\n const analytics = {\r\n totalQueries: queryHistory.length,\r\n slowQueries: queryHistory.filter(q => q.executionTimeMs > this.slowQueryThresholdMs).length,\r\n avgExecutionTime: 0,\r\n p95ExecutionTime: 0,\r\n errorRate: 0,\r\n mostFrequentTables: [] as Array<{ table: string; count: number }>,\r\n performanceTrend: 'stable' as 'improving' | 'stable' | 'degrading'\r\n };\r\n\r\n if (queryHistory.length === 0) return analytics;\r\n\r\n // Calculate metrics\r\n const executionTimes = queryHistory.map(q => q.executionTimeMs).sort((a, b) => a - b);\r\n analytics.avgExecutionTime = executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length;\r\n analytics.p95ExecutionTime = executionTimes[Math.floor(executionTimes.length * 0.95)];\r\n analytics.errorRate = (queryHistory.filter(q => q.error).length / queryHistory.length) * 100;\r\n\r\n // Table usage analysis\r\n const tableUsage = new Map<string, number>();\r\n for (const query of queryHistory) {\r\n for (const table of query.tables) {\r\n tableUsage.set(table, (tableUsage.get(table) || 0) + 1);\r\n }\r\n }\r\n\r\n analytics.mostFrequentTables = Array.from(tableUsage.entries())\r\n .map(([table, count]) => ({ table, count }))\r\n .sort((a, b) => b.count - a.count)\r\n .slice(0, 10);\r\n\r\n // Performance trend (simple analysis of recent vs older queries)\r\n const midpoint = Math.floor(queryHistory.length / 2);\r\n const recentAvg = executionTimes.slice(midpoint).reduce((a, b) => a + b, 0) / (executionTimes.length - midpoint);\r\n const olderAvg = executionTimes.slice(0, midpoint).reduce((a, b) => a + b, 0) / midpoint;\r\n\r\n if (recentAvg < olderAvg * 0.8) analytics.performanceTrend = 'improving';\r\n else if (recentAvg > olderAvg * 1.2) analytics.performanceTrend = 'degrading';\r\n\r\n return analytics;\r\n }\r\n\r\n // Helper methods\r\n\r\n private countSelectColumns(sql: string): number {\r\n const selectMatch = sql.match(/SELECT\\s+(.+?)\\s+FROM/i);\r\n if (!selectMatch) return 0;\r\n\r\n const selectClause = selectMatch[1];\r\n if (selectClause.includes('*')) return 1;\r\n\r\n return (selectClause.match(/,/g) || []).length + 1;\r\n }\r\n\r\n private countWhereConditions(sql: string): number {\r\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+(GROUP|ORDER|LIMIT|$))/i);\r\n if (!whereMatch) return 0;\r\n\r\n const whereClause = whereMatch[1];\r\n return (whereClause.match(/\\bAND\\b/gi) || []).length + 1;\r\n }\r\n\r\n private countJoins(sql: string): number {\r\n return (sql.match(/\\bJOIN\\b/gi) || []).length;\r\n }\r\n\r\n private countSubqueries(sql: string): number {\r\n return (sql.match(/\\(\\s*SELECT/gi) || []).length;\r\n }\r\n\r\n private extractColumnsFromCondition(condition: string, tables: string[], schema: DatabaseSchema): Array<{ table: string; column: string }> {\r\n const columns: Array<{ table: string; column: string }> = [];\r\n\r\n // Simple column extraction (table.column or just column)\r\n const columnMatches = condition.match(/\\b(\\w+\\.)?(\\w+)\\b/g) || [];\r\n\r\n for (const match of columnMatches) {\r\n if (match.includes('.')) {\r\n const [table, column] = match.split('.');\r\n if (tables.includes(table)) {\r\n columns.push({ table, column });\r\n }\r\n } else {\r\n // Ambiguous column, check all tables\r\n const column = match;\r\n for (const table of tables) {\r\n const tableMeta = this.findTableInSchema(schema, table);\r\n if (tableMeta?.columns.some(col => col.name === column)) {\r\n columns.push({ table, column });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return columns;\r\n }\r\n\r\n private analyzeExplainPlan(plan: any): PerformanceBottleneck[] {\r\n const bottlenecks: PerformanceBottleneck[] = [];\r\n\r\n // This is a simplified analysis - real implementation would parse database-specific EXPLAIN formats\r\n const planStr = JSON.stringify(plan).toLowerCase();\r\n\r\n if (planStr.includes('table scan') || planStr.includes('seq scan')) {\r\n bottlenecks.push({\r\n type: 'table_scan',\r\n severity: 'high',\r\n description: 'Full table scan detected - consider adding indexes',\r\n estimatedCost: 100\r\n });\r\n }\r\n\r\n if (planStr.includes('sort') && !planStr.includes('index')) {\r\n bottlenecks.push({\r\n type: 'sort',\r\n severity: 'medium',\r\n description: 'In-memory sort operation - consider indexed ORDER BY',\r\n estimatedCost: 50\r\n });\r\n }\r\n\r\n return bottlenecks;\r\n }\r\n\r\n private canRemoveDistinct(sql: string, _schema: DatabaseSchema): boolean {\r\n // Simple heuristic: if query has GROUP BY or primary key is selected, DISTINCT might be unnecessary\r\n return /\\bGROUP\\s+BY\\b/i.test(sql) || /\\bPRIMARY\\s+KEY\\b/i.test(sql);\r\n }\r\n\r\n private findTableInSchema(schema: DatabaseSchema, tableName: string) {\r\n for (const schemaMeta of schema.schemas) {\r\n const table = schemaMeta.tables.find(t => t.name === tableName);\r\n if (table) return table;\r\n }\r\n return null;\r\n }\r\n\r\n private generateQueryId(sql: string): string {\r\n // Simple hash for query identification\r\n let hash = 0;\r\n for (let i = 0; i < sql.length; i++) {\r\n const char = sql.charCodeAt(i);\r\n hash = ((hash << 5) - hash) + char;\r\n hash = hash & hash; // Convert to 32-bit integer\r\n }\r\n return Math.abs(hash).toString(16);\r\n }\r\n}","import { QueryHistoryEntry, QueryComplexity } from './types.js';\r\nimport { extractTableNames } from './utils.js';\r\nimport { QueryOptimizer } from './query-optimizer.js';\r\n\r\nexport class QueryTracker {\r\n private history = new Map<string, QueryHistoryEntry[]>();\r\n private maxHistoryPerDb = 100;\r\n private optimizer = new QueryOptimizer();\r\n\r\n track(\r\n dbId: string,\r\n sql: string,\r\n executionTimeMs: number,\r\n rowCount: number,\r\n error?: string,\r\n explainPlan?: any\r\n ): void {\r\n const complexity = this.optimizer.analyzeQueryComplexity(sql);\r\n\r\n const entry: QueryHistoryEntry = {\r\n timestamp: new Date(),\r\n sql,\r\n tables: extractTableNames(sql),\r\n executionTimeMs,\r\n rowCount,\r\n error,\r\n explainPlan,\r\n queryComplexity: complexity,\r\n performanceScore: this.calculatePerformanceScore(executionTimeMs, complexity)\r\n };\r\n\r\n if (!this.history.has(dbId)) {\r\n this.history.set(dbId, []);\r\n }\r\n\r\n const dbHistory = this.history.get(dbId)!;\r\n dbHistory.push(entry);\r\n\r\n // Keep only recent queries\r\n if (dbHistory.length > this.maxHistoryPerDb) {\r\n dbHistory.shift();\r\n }\r\n }\r\n\r\n getHistory(dbId: string, limit?: number): QueryHistoryEntry[] {\r\n const dbHistory = this.history.get(dbId) || [];\r\n if (limit) {\r\n return dbHistory.slice(-limit);\r\n }\r\n return [...dbHistory];\r\n }\r\n\r\n getStats(dbId: string): {\r\n totalQueries: number;\r\n avgExecutionTime: number;\r\n errorCount: number;\r\n tableUsage: Record<string, number>;\r\n performanceMetrics: {\r\n avgScore: number;\r\n slowQueryCount: number;\r\n complexityDistribution: Record<string, number>;\r\n };\r\n } {\r\n const dbHistory = this.history.get(dbId) || [];\r\n\r\n const stats = {\r\n totalQueries: dbHistory.length,\r\n avgExecutionTime: 0,\r\n errorCount: 0,\r\n tableUsage: {} as Record<string, number>,\r\n performanceMetrics: {\r\n avgScore: 0,\r\n slowQueryCount: 0,\r\n complexityDistribution: {} as Record<string, number>\r\n }\r\n };\r\n\r\n if (dbHistory.length === 0) {\r\n return stats;\r\n }\r\n\r\n let totalTime = 0;\r\n let totalScore = 0;\r\n\r\n for (const entry of dbHistory) {\r\n totalTime += entry.executionTimeMs;\r\n if (entry.error) {\r\n stats.errorCount++;\r\n }\r\n\r\n if (entry.performanceScore !== undefined) {\r\n totalScore += entry.performanceScore;\r\n }\r\n\r\n if (entry.executionTimeMs > 1000) { // Configurable threshold\r\n stats.performanceMetrics.slowQueryCount++;\r\n }\r\n\r\n if (entry.queryComplexity) {\r\n const complexity = entry.queryComplexity.estimatedComplexity;\r\n stats.performanceMetrics.complexityDistribution[complexity] =\r\n (stats.performanceMetrics.complexityDistribution[complexity] || 0) + 1;\r\n }\r\n\r\n for (const table of entry.tables) {\r\n stats.tableUsage[table] = (stats.tableUsage[table] || 0) + 1;\r\n }\r\n }\r\n\r\n stats.avgExecutionTime = totalTime / dbHistory.length;\r\n stats.performanceMetrics.avgScore = totalScore / dbHistory.length;\r\n\r\n return stats;\r\n }\r\n\r\n getPerformanceAnalytics(dbId: string) {\r\n const history = this.getHistory(dbId);\r\n return this.optimizer.getPerformanceAnalytics(history);\r\n }\r\n\r\n getIndexRecommendations(dbId: string, schema: any) {\r\n const history = this.getHistory(dbId);\r\n return this.optimizer.generateIndexRecommendations(history, schema);\r\n }\r\n\r\n getSlowQueryAlerts(dbId: string) {\r\n const history = this.getHistory(dbId);\r\n return this.optimizer.detectSlowQueries(history, dbId);\r\n }\r\n\r\n suggestQueryRewrite(sql: string, schema: any) {\r\n return this.optimizer.suggestQueryRewrites(sql, schema);\r\n }\r\n\r\n async profileQueryPerformance(dbId: string, sql: string, explainResult: any, executionTimeMs: number, rowCount: number) {\r\n return this.optimizer.profileQueryPerformance(dbId, sql, explainResult, executionTimeMs, rowCount);\r\n }\r\n\r\n clear(dbId?: string): void {\r\n if (dbId) {\r\n this.history.delete(dbId);\r\n } else {\r\n this.history.clear();\r\n }\r\n }\r\n\r\n private calculatePerformanceScore(executionTimeMs: number, complexity: QueryComplexity): number {\r\n // Simple scoring algorithm: penalize slow queries and complex queries\r\n let score = 100;\r\n\r\n // Time-based penalty\r\n if (executionTimeMs > 5000) score -= 40;\r\n else if (executionTimeMs > 1000) score -= 20;\r\n else if (executionTimeMs > 100) score -= 10;\r\n\r\n // Complexity-based penalty\r\n const complexityPenalty = {\r\n simple: 0,\r\n medium: 5,\r\n complex: 15,\r\n very_complex: 25\r\n };\r\n score -= complexityPenalty[complexity.estimatedComplexity];\r\n\r\n return Math.max(0, Math.min(100, score));\r\n }\r\n}\r\n","import { DatabaseAdapter, DatabaseConfig, IntrospectionOptions, QueryResult } from './types.js';\r\nimport { createAdapter } from './adapters/index.js';\r\nimport { SchemaCache, CacheEntry } from './cache.js';\r\nimport { QueryTracker } from './query-tracker.js';\r\nimport { isWriteOperation, findJoinPaths } from './utils.js';\r\nimport { getLogger } from './logger.js';\r\n\r\nexport interface DatabaseManagerOptions {\r\n cacheDir: string;\r\n cacheTtlMinutes: number;\r\n allowWrite: boolean;\r\n allowedWriteOperations?: string[];\r\n disableDangerousOperations: boolean;\r\n}\r\n\r\nexport class DatabaseManager {\r\n private logger = getLogger();\r\n private adapters = new Map<string, DatabaseAdapter>();\r\n private cache: SchemaCache;\r\n private queryTracker = new QueryTracker();\r\n\r\n constructor(\r\n private _configs: DatabaseConfig[],\r\n private options: DatabaseManagerOptions\r\n ) {\r\n this.cache = new SchemaCache(options.cacheDir, options.cacheTtlMinutes);\r\n }\r\n\r\n async init(): Promise<void> {\r\n await this.cache.init();\r\n\r\n // Create adapters\r\n for (const config of this._configs) {\r\n const adapter = createAdapter(config);\r\n this.adapters.set(config.id, adapter);\r\n\r\n // Connect eagerly if configured\r\n if (config.eagerConnect) {\r\n try {\r\n await this.connect(config.id);\r\n } catch (error) {\r\n this.logger.error({ dbId: config.id, error }, 'Failed to eager connect');\r\n }\r\n }\r\n }\r\n\r\n this.logger.info({ databases: this._configs.length }, 'Database manager initialized');\r\n }\r\n\r\n async shutdown(): Promise<void> {\r\n for (const [dbId, adapter] of this.adapters) {\r\n try {\r\n await adapter.disconnect();\r\n } catch (error) {\r\n this.logger.error({ dbId, error }, 'Failed to disconnect');\r\n }\r\n }\r\n this.logger.info('Database manager shut down');\r\n }\r\n\r\n getConfigs(): DatabaseConfig[] {\r\n return this._configs;\r\n }\r\n\r\n getConfig(dbId: string): DatabaseConfig | undefined {\r\n return this._configs.find((c) => c.id === dbId);\r\n }\r\n\r\n private getAdapter(dbId: string): DatabaseAdapter {\r\n const adapter = this.adapters.get(dbId);\r\n if (!adapter) {\r\n throw new Error(`Database not found: ${dbId}`);\r\n }\r\n return adapter;\r\n }\r\n\r\n private async connect(dbId: string): Promise<void> {\r\n const adapter = this.getAdapter(dbId);\r\n await adapter.connect();\r\n }\r\n\r\n private async ensureConnected(dbId: string): Promise<void> {\r\n const adapter = this.getAdapter(dbId);\r\n const connected = await adapter.testConnection();\r\n if (!connected) {\r\n await this.connect(dbId);\r\n }\r\n }\r\n\r\n async testConnection(dbId: string): Promise<boolean> {\r\n const adapter = this.getAdapter(dbId);\r\n return adapter.testConnection();\r\n }\r\n\r\n async getVersion(dbId: string): Promise<string> {\r\n await this.ensureConnected(dbId);\r\n const adapter = this.getAdapter(dbId);\r\n return adapter.getVersion();\r\n }\r\n\r\n async introspectSchema(\r\n dbId: string,\r\n forceRefresh: boolean = false,\r\n options?: IntrospectionOptions\r\n ): Promise<CacheEntry> {\r\n // Check cache first\r\n if (!forceRefresh) {\r\n const cached = await this.cache.get(dbId);\r\n if (cached) {\r\n this.logger.debug({ dbId }, 'Using cached schema');\r\n return cached;\r\n }\r\n }\r\n\r\n // Acquire lock to prevent concurrent introspection\r\n const releaseLock = await this.cache.acquireIntrospectionLock(dbId);\r\n\r\n try {\r\n // Double-check cache after acquiring lock\r\n if (!forceRefresh) {\r\n const cached = await this.cache.get(dbId);\r\n if (cached) {\r\n return cached;\r\n }\r\n }\r\n\r\n this.logger.info({ dbId, forceRefresh }, 'Introspecting schema');\r\n\r\n await this.ensureConnected(dbId);\r\n const adapter = this.getAdapter(dbId);\r\n const schema = await adapter.introspect(options);\r\n\r\n // Cache the result\r\n const config = this.getConfig(dbId);\r\n await this.cache.set(dbId, schema, config?.introspection?.maxTables);\r\n\r\n const entry = await this.cache.get(dbId);\r\n return entry!;\r\n } finally {\r\n releaseLock();\r\n }\r\n }\r\n\r\n async getSchema(dbId: string): Promise<CacheEntry> {\r\n // Ensure schema is cached\r\n return this.introspectSchema(dbId, false);\r\n }\r\n\r\n async runQuery(\r\n dbId: string,\r\n sql: string,\r\n params: any[] = [],\r\n timeoutMs?: number\r\n ): Promise<QueryResult> {\r\n const config = this.getConfig(dbId);\r\n \r\n // Check if write operation\r\n if (isWriteOperation(sql)) {\r\n if (!this.options.allowWrite && !config?.readOnly === false) {\r\n throw new Error('Write operations are not allowed. Set allowWrite in config.');\r\n }\r\n\r\n // Check for dangerous operations (DELETE, TRUNCATE, DROP)\r\n if (this.options.disableDangerousOperations) {\r\n const operation = sql.trim().split(/\\s+/)[0].toUpperCase();\r\n const dangerousOps = ['DELETE', 'TRUNCATE', 'DROP'];\r\n if (dangerousOps.includes(operation)) {\r\n throw new Error(`Dangerous operation ${operation} is disabled. Set disableDangerousOperations: false in security config to allow.`);\r\n }\r\n }\r\n\r\n // Check allowed operations\r\n if (this.options.allowedWriteOperations && this.options.allowedWriteOperations.length > 0) {\r\n const operation = sql.trim().split(/\\s+/)[0].toUpperCase();\r\n if (!this.options.allowedWriteOperations.includes(operation)) {\r\n throw new Error(`Write operation ${operation} is not allowed.`);\r\n }\r\n }\r\n }\r\n\r\n // Ensure schema is cached (for relationship annotation)\r\n await this.introspectSchema(dbId, false);\r\n\r\n await this.ensureConnected(dbId);\r\n const adapter = this.getAdapter(dbId);\r\n\r\n try {\r\n const result = await adapter.query(sql, params, timeoutMs);\r\n \r\n // Get EXPLAIN plan for performance analysis (if not a write operation)\r\n let explainPlan;\r\n if (!isWriteOperation(sql)) {\r\n try {\r\n explainPlan = await adapter.explain(sql, params);\r\n } catch (_explainError) {\r\n // EXPLAIN might not be supported or might fail, continue without it\r\n this.logger.debug({ dbId, sql }, 'EXPLAIN failed, continuing without performance analysis');\r\n }\r\n }\r\n \r\n // Track query with performance data\r\n this.queryTracker.track(dbId, sql, result.executionTimeMs, result.rowCount, undefined, explainPlan);\r\n\r\n return result;\r\n } catch (error: any) {\r\n // Track error\r\n this.queryTracker.track(dbId, sql, 0, 0, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async explainQuery(dbId: string, sql: string, params: any[] = []): Promise<any> {\r\n await this.ensureConnected(dbId);\r\n const adapter = this.getAdapter(dbId);\r\n return adapter.explain(sql, params);\r\n }\r\n\r\n async suggestJoins(dbId: string, tables: string[]): Promise<any[]> {\r\n const cacheEntry = await this.getSchema(dbId);\r\n return findJoinPaths(tables, cacheEntry.relationships);\r\n }\r\n\r\n async clearCache(dbId?: string): Promise<void> {\r\n await this.cache.clear(dbId);\r\n this.queryTracker.clear(dbId);\r\n }\r\n\r\n async getCacheStatus(dbId?: string): Promise<any[]> {\r\n return this.cache.getStatus(dbId);\r\n }\r\n\r\n getQueryStats(dbId: string): any {\r\n return this.queryTracker.getStats(dbId);\r\n }\r\n\r\n getQueryHistory(dbId: string, limit?: number): any[] {\r\n return this.queryTracker.getHistory(dbId, limit);\r\n }\r\n\r\n getPerformanceAnalytics(dbId: string): any {\r\n return this.queryTracker.getPerformanceAnalytics(dbId);\r\n }\r\n\r\n async getIndexRecommendations(dbId: string): Promise<any[]> {\r\n const schema = await this.getSchema(dbId);\r\n return this.queryTracker.getIndexRecommendations(dbId, schema);\r\n }\r\n\r\n getSlowQueryAlerts(dbId: string): any[] {\r\n return this.queryTracker.getSlowQueryAlerts(dbId);\r\n }\r\n\r\n async suggestQueryRewrite(dbId: string, sql: string): Promise<any> {\r\n const schema = await this.getSchema(dbId);\r\n return this.queryTracker.suggestQueryRewrite(sql, schema);\r\n }\r\n\r\n async profileQueryPerformance(dbId: string, sql: string, params: any[] = []): Promise<any> {\r\n await this.ensureConnected(dbId);\r\n const adapter = this.getAdapter(dbId);\r\n \r\n // Execute query to get timing\r\n const startTime = Date.now();\r\n const result = await adapter.query(sql, params);\r\n const executionTimeMs = Date.now() - startTime;\r\n \r\n // Get EXPLAIN plan\r\n const explainResult = await adapter.explain(sql, params);\r\n \r\n return this.queryTracker.profileQueryPerformance(dbId, sql, explainResult, executionTimeMs, result.rowCount);\r\n }\r\n}\r\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport {\r\n CallToolRequestSchema,\r\n ListToolsRequestSchema,\r\n ListResourcesRequestSchema,\r\n ReadResourceRequestSchema,\r\n InitializeRequestSchema,\r\n} from '@modelcontextprotocol/sdk/types.js';\r\nimport { DatabaseManager } from './database-manager.js';\r\nimport { ServerConfig } from './types.js';\r\nimport { getLogger } from './logger.js';\r\nimport { redactUrl } from './utils.js';\r\n\r\nexport class MCPServer {\r\n private server: Server;\r\n private logger = getLogger();\r\n\r\n constructor(\r\n private _dbManager: DatabaseManager,\r\n private _config: ServerConfig\r\n ) {\r\n this.server = new Server(\r\n {\r\n name: 'mcp-database-server',\r\n version: '1.0.0',\r\n },\r\n {\r\n capabilities: {\r\n tools: {},\r\n resources: {},\r\n },\r\n }\r\n );\r\n\r\n this.setupHandlers();\r\n }\r\n\r\n private setupHandlers(): void {\r\n // Handle initialization\r\n this.server.setRequestHandler(InitializeRequestSchema, async (request) => {\r\n const { protocolVersion } = request.params;\r\n this.logger.info({ protocolVersion }, 'MCP server initializing');\r\n\r\n return {\r\n protocolVersion,\r\n capabilities: {\r\n tools: {},\r\n resources: {},\r\n },\r\n serverInfo: {\r\n name: 'mcp-database-server',\r\n version: '1.0.0',\r\n },\r\n };\r\n });\r\n\r\n // List available tools\r\n this.server.setRequestHandler(ListToolsRequestSchema, async () => ({\r\n tools: [\r\n {\r\n name: 'list_databases',\r\n description: 'List all configured databases with their status',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {},\r\n },\r\n },\r\n {\r\n name: 'introspect_schema',\r\n description: 'Introspect database schema and cache it',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID to introspect',\r\n },\r\n forceRefresh: {\r\n type: 'boolean',\r\n description: 'Force refresh even if cached',\r\n default: false,\r\n },\r\n schemaFilter: {\r\n type: 'object',\r\n description: 'Optional schema filtering options',\r\n properties: {\r\n includeSchemas: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n },\r\n excludeSchemas: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n },\r\n includeViews: { type: 'boolean' },\r\n maxTables: { type: 'number' },\r\n },\r\n },\r\n },\r\n required: ['dbId'],\r\n },\r\n },\r\n {\r\n name: 'get_schema',\r\n description: 'Get cached schema metadata',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n schema: {\r\n type: 'string',\r\n description: 'Optional schema name to filter',\r\n },\r\n table: {\r\n type: 'string',\r\n description: 'Optional table name to filter',\r\n },\r\n },\r\n required: ['dbId'],\r\n },\r\n },\r\n {\r\n name: 'run_query',\r\n description: 'Execute SQL query against a database',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n sql: {\r\n type: 'string',\r\n description: 'SQL query to execute',\r\n },\r\n params: {\r\n type: 'array',\r\n description: 'Query parameters',\r\n items: {},\r\n },\r\n limit: {\r\n type: 'number',\r\n description: 'Maximum number of rows to return',\r\n },\r\n timeoutMs: {\r\n type: 'number',\r\n description: 'Query timeout in milliseconds',\r\n },\r\n },\r\n required: ['dbId', 'sql'],\r\n },\r\n },\r\n {\r\n name: 'explain_query',\r\n description: 'Get query execution plan',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n sql: {\r\n type: 'string',\r\n description: 'SQL query to explain',\r\n },\r\n params: {\r\n type: 'array',\r\n description: 'Query parameters',\r\n items: {},\r\n },\r\n },\r\n required: ['dbId', 'sql'],\r\n },\r\n },\r\n {\r\n name: 'suggest_joins',\r\n description: 'Suggest join paths between tables based on relationships',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n tables: {\r\n type: 'array',\r\n description: 'List of table names to join',\r\n items: { type: 'string' },\r\n minItems: 2,\r\n },\r\n },\r\n required: ['dbId', 'tables'],\r\n },\r\n },\r\n {\r\n name: 'clear_cache',\r\n description: 'Clear schema cache',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Optional database ID (clears all if omitted)',\r\n },\r\n },\r\n },\r\n },\r\n {\r\n name: 'cache_status',\r\n description: 'Get cache status and statistics',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Optional database ID',\r\n },\r\n },\r\n },\r\n },\r\n {\r\n name: 'health_check',\r\n description: 'Check database connectivity and get version info',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Optional database ID (checks all if omitted)',\r\n },\r\n },\r\n },\r\n },\r\n {\r\n name: 'analyze_performance',\r\n description: 'Get detailed performance analytics for a database',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID to analyze',\r\n },\r\n },\r\n required: ['dbId'],\r\n },\r\n },\r\n {\r\n name: 'suggest_indexes',\r\n description: 'Analyze query patterns and suggest optimal indexes',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID to analyze',\r\n },\r\n },\r\n required: ['dbId'],\r\n },\r\n },\r\n {\r\n name: 'detect_slow_queries',\r\n description: 'Identify and alert on slow-running queries',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID to analyze',\r\n },\r\n },\r\n required: ['dbId'],\r\n },\r\n },\r\n {\r\n name: 'rewrite_query',\r\n description: 'Suggest optimized versions of SQL queries',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n sql: {\r\n type: 'string',\r\n description: 'SQL query to optimize',\r\n },\r\n },\r\n required: ['dbId', 'sql'],\r\n },\r\n },\r\n {\r\n name: 'profile_query',\r\n description: 'Profile query performance with detailed analysis',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n dbId: {\r\n type: 'string',\r\n description: 'Database ID',\r\n },\r\n sql: {\r\n type: 'string',\r\n description: 'SQL query to profile',\r\n },\r\n params: {\r\n type: 'array',\r\n description: 'Query parameters',\r\n items: {},\r\n },\r\n },\r\n required: ['dbId', 'sql'],\r\n },\r\n },\r\n ],\r\n }));\r\n\r\n // Handle tool calls\r\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\r\n const { name, arguments: args } = request.params;\r\n\r\n try {\r\n switch (name) {\r\n case 'list_databases':\r\n return await this.handleListDatabases();\r\n\r\n case 'introspect_schema':\r\n return await this.handleIntrospectSchema(args as any);\r\n\r\n case 'get_schema':\r\n return await this.handleGetSchema(args as any);\r\n\r\n case 'run_query':\r\n return await this.handleRunQuery(args as any);\r\n\r\n case 'explain_query':\r\n return await this.handleExplainQuery(args as any);\r\n\r\n case 'suggest_joins':\r\n return await this.handleSuggestJoins(args as any);\r\n\r\n case 'clear_cache':\r\n return await this.handleClearCache(args as any);\r\n\r\n case 'cache_status':\r\n return await this.handleCacheStatus(args as any);\r\n\r\n case 'health_check':\r\n return await this.handleHealthCheck(args as any);\r\n\r\n case 'analyze_performance':\r\n return await this.handleAnalyzePerformance(args as any);\r\n\r\n case 'suggest_indexes':\r\n return await this.handleSuggestIndexes(args as any);\r\n\r\n case 'detect_slow_queries':\r\n return await this.handleDetectSlowQueries(args as any);\r\n\r\n case 'rewrite_query':\r\n return await this.handleRewriteQuery(args as any);\r\n\r\n case 'profile_query':\r\n return await this.handleProfileQuery(args as any);\r\n\r\n default:\r\n throw new Error(`Unknown tool: ${name}`);\r\n }\r\n } catch (error: any) {\r\n this.logger.error({ tool: name, error }, 'Tool execution failed');\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify({\r\n error: error.message,\r\n code: error.code || 'TOOL_ERROR',\r\n }),\r\n },\r\n ],\r\n };\r\n }\r\n });\r\n\r\n // List resources (cached schemas)\r\n this.server.setRequestHandler(ListResourcesRequestSchema, async () => {\r\n const statuses = await this._dbManager.getCacheStatus();\r\n const resources = statuses\r\n .filter((s) => s.exists)\r\n .map((s) => ({\r\n uri: `schema://${s.dbId}`,\r\n name: `Schema: ${s.dbId}`,\r\n description: `Cached schema for ${s.dbId} (${s.tableCount} tables, ${s.relationshipCount} relationships)`,\r\n mimeType: 'application/json',\r\n }));\r\n\r\n return { resources };\r\n });\r\n\r\n // Read resource (return cached schema)\r\n this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\r\n const uri = request.params.uri;\r\n const match = uri.match(/^schema:\\/\\/(.+)$/);\r\n\r\n if (!match) {\r\n throw new Error(`Invalid resource URI: ${uri}`);\r\n }\r\n\r\n const dbId = match[1];\r\n const cacheEntry = await this._dbManager.getSchema(dbId);\r\n\r\n return {\r\n contents: [\r\n {\r\n uri,\r\n mimeType: 'application/json',\r\n text: JSON.stringify(cacheEntry, null, 2),\r\n },\r\n ],\r\n };\r\n });\r\n }\r\n\r\n private async handleListDatabases() {\r\n const configs = this._dbManager.getConfigs();\r\n const statuses = await Promise.all(\r\n configs.map(async (config) => {\r\n const connected = await this._dbManager.testConnection(config.id);\r\n const cacheStatus = (await this._dbManager.getCacheStatus(config.id))[0];\r\n\r\n return {\r\n id: config.id,\r\n type: config.type,\r\n url: this._config.security?.redactSecrets ? redactUrl(config.url || '') : config.url,\r\n connected,\r\n cached: cacheStatus?.exists || false,\r\n cacheAge: cacheStatus?.age,\r\n version: cacheStatus?.version,\r\n };\r\n })\r\n );\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(statuses, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleIntrospectSchema(args: {\r\n dbId: string;\r\n forceRefresh?: boolean;\r\n schemaFilter?: any;\r\n }) {\r\n const result = await this._dbManager.introspectSchema(\r\n args.dbId,\r\n args.forceRefresh || false,\r\n args.schemaFilter\r\n );\r\n\r\n const summary = {\r\n dbId: args.dbId,\r\n version: result.schema.version,\r\n introspectedAt: result.schema.introspectedAt,\r\n schemas: result.schema.schemas.map((s) => ({\r\n name: s.name,\r\n tableCount: s.tables.length,\r\n viewCount: s.tables.filter((t) => t.type === 'view').length,\r\n })),\r\n totalTables: result.schema.schemas.reduce((sum, s) => sum + s.tables.length, 0),\r\n totalRelationships: result.relationships.length,\r\n };\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(summary, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleGetSchema(args: { dbId: string; schema?: string; table?: string }) {\r\n const cacheEntry = await this._dbManager.getSchema(args.dbId);\r\n let result: any = cacheEntry.schema;\r\n\r\n // Filter by schema\r\n if (args.schema) {\r\n result = {\r\n ...result,\r\n schemas: result.schemas.filter((s: any) => s.name === args.schema),\r\n };\r\n }\r\n\r\n // Filter by table\r\n if (args.table) {\r\n result = {\r\n ...result,\r\n schemas: result.schemas.map((s: any) => ({\r\n ...s,\r\n tables: s.tables.filter((t: any) => t.name === args.table),\r\n })),\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(result, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleRunQuery(args: {\r\n dbId: string;\r\n sql: string;\r\n params?: any[];\r\n limit?: number;\r\n timeoutMs?: number;\r\n }) {\r\n let sql = args.sql;\r\n\r\n // Apply row limit if specified\r\n if (args.limit && !sql.toUpperCase().includes('LIMIT')) {\r\n sql += ` LIMIT ${args.limit}`;\r\n }\r\n\r\n const result = await this._dbManager.runQuery(args.dbId, sql, args.params, args.timeoutMs);\r\n\r\n // Get relevant relationships for the query\r\n const cacheEntry = await this._dbManager.getSchema(args.dbId);\r\n const queryStats = this._dbManager.getQueryStats(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(\r\n {\r\n ...result,\r\n metadata: {\r\n relationships: cacheEntry.relationships.filter((r) =>\r\n result.columns.some(\r\n (col) =>\r\n col.includes(r.fromTable) ||\r\n col.includes(r.toTable)\r\n )\r\n ),\r\n queryStats,\r\n },\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleExplainQuery(args: { dbId: string; sql: string; params?: any[] }) {\r\n const result = await this._dbManager.explainQuery(args.dbId, args.sql, args.params);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(result, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleSuggestJoins(args: { dbId: string; tables: string[] }) {\r\n const joinPaths = await this._dbManager.suggestJoins(args.dbId, args.tables);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(joinPaths, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleClearCache(args: { dbId?: string }) {\r\n await this._dbManager.clearCache(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify({\r\n success: true,\r\n message: args.dbId ? `Cache cleared for ${args.dbId}` : 'All caches cleared',\r\n }),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleCacheStatus(args: { dbId?: string }) {\r\n const statuses = await this._dbManager.getCacheStatus(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(statuses, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleHealthCheck(args: { dbId?: string }) {\r\n const configs = args.dbId\r\n ? [this._dbManager.getConfig(args.dbId)!]\r\n : this._dbManager.getConfigs();\r\n\r\n const results = await Promise.all(\r\n configs.map(async (config) => {\r\n try {\r\n const connected = await this._dbManager.testConnection(config.id);\r\n const version = connected ? await this._dbManager.getVersion(config.id) : 'N/A';\r\n\r\n return {\r\n dbId: config.id,\r\n healthy: connected,\r\n version,\r\n };\r\n } catch (error: any) {\r\n return {\r\n dbId: config.id,\r\n healthy: false,\r\n error: error.message,\r\n };\r\n }\r\n })\r\n );\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(results, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleAnalyzePerformance(args: { dbId: string }) {\r\n const analytics = this._dbManager.getPerformanceAnalytics(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(analytics, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleSuggestIndexes(args: { dbId: string }) {\r\n const recommendations = await this._dbManager.getIndexRecommendations(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(recommendations, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleDetectSlowQueries(args: { dbId: string }) {\r\n const alerts = this._dbManager.getSlowQueryAlerts(args.dbId);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(alerts, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleRewriteQuery(args: { dbId: string; sql: string }) {\r\n const suggestion = await this._dbManager.suggestQueryRewrite(args.dbId, args.sql);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(suggestion, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n private async handleProfileQuery(args: {\r\n dbId: string;\r\n sql: string;\r\n params?: any[];\r\n }) {\r\n const profile = await this._dbManager.profileQueryPerformance(args.dbId, args.sql, args.params);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: JSON.stringify(profile, null, 2),\r\n },\r\n ],\r\n };\r\n }\r\n\r\n async start(): Promise<void> {\r\n console.error('Starting MCP server...');\r\n const transport = new StdioServerTransport();\r\n console.error('Created transport, connecting...');\r\n await this.server.connect(transport);\r\n console.error('MCP server connected and started');\r\n this.logger.info('MCP server started');\r\n }\r\n}\r\n"],"mappings":"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","names":["existsSync","dirname","join","path","resolve","fs","fs","resolve","version","__filename","__dirname","dirname","join","existsSync","logger"]}