@cmd233/mcp-database-server 1.1.1

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.
@@ -0,0 +1,186 @@
1
+ import sql from 'mssql';
2
+ /**
3
+ * SQL Server database adapter implementation
4
+ */
5
+ export class SqlServerAdapter {
6
+ constructor(connectionInfo) {
7
+ this.pool = null;
8
+ this.server = connectionInfo.server;
9
+ this.database = connectionInfo.database;
10
+ // Create SQL Server connection config
11
+ this.config = {
12
+ server: connectionInfo.server,
13
+ database: connectionInfo.database,
14
+ port: connectionInfo.port || 1433,
15
+ options: {
16
+ trustServerCertificate: connectionInfo.trustServerCertificate ?? true,
17
+ ...connectionInfo.options
18
+ }
19
+ };
20
+ // Add authentication options
21
+ if (connectionInfo.user && connectionInfo.password) {
22
+ this.config.user = connectionInfo.user;
23
+ this.config.password = connectionInfo.password;
24
+ }
25
+ else {
26
+ // Use Windows authentication if no username/password provided
27
+ this.config.options.trustedConnection = true;
28
+ this.config.options.enableArithAbort = true;
29
+ }
30
+ }
31
+ /**
32
+ * Initialize SQL Server connection
33
+ */
34
+ async init() {
35
+ try {
36
+ console.error(`[INFO] Connecting to SQL Server: ${this.server}, Database: ${this.database}`);
37
+ this.pool = await new sql.ConnectionPool(this.config).connect();
38
+ console.error(`[INFO] SQL Server connection established successfully`);
39
+ }
40
+ catch (err) {
41
+ console.error(`[ERROR] SQL Server connection error: ${err.message}`);
42
+ throw new Error(`Failed to connect to SQL Server: ${err.message}`);
43
+ }
44
+ }
45
+ /**
46
+ * Execute a SQL query and get all results
47
+ * @param query SQL query to execute
48
+ * @param params Query parameters
49
+ * @returns Promise with query results
50
+ */
51
+ async all(query, params = []) {
52
+ if (!this.pool) {
53
+ throw new Error("Database not initialized");
54
+ }
55
+ try {
56
+ const request = this.pool.request();
57
+ // Add parameters to the request
58
+ params.forEach((param, index) => {
59
+ request.input(`param${index}`, param);
60
+ });
61
+ // Replace ? with named parameters
62
+ const preparedQuery = query.replace(/\?/g, (_, i) => `@param${i}`);
63
+ const result = await request.query(preparedQuery);
64
+ return result.recordset;
65
+ }
66
+ catch (err) {
67
+ throw new Error(`SQL Server query error: ${err.message}`);
68
+ }
69
+ }
70
+ /**
71
+ * Execute a SQL query that modifies data
72
+ * @param query SQL query to execute
73
+ * @param params Query parameters
74
+ * @returns Promise with result info
75
+ */
76
+ async run(query, params = []) {
77
+ if (!this.pool) {
78
+ throw new Error("Database not initialized");
79
+ }
80
+ try {
81
+ const request = this.pool.request();
82
+ // Add parameters to the request
83
+ params.forEach((param, index) => {
84
+ request.input(`param${index}`, param);
85
+ });
86
+ // Replace ? with named parameters
87
+ const preparedQuery = query.replace(/\?/g, (_, i) => `@param${i}`);
88
+ // Add output parameter for identity value if it's an INSERT
89
+ let lastID = 0;
90
+ if (query.trim().toUpperCase().startsWith('INSERT')) {
91
+ request.output('insertedId', sql.Int, 0);
92
+ const updatedQuery = `${preparedQuery}; SELECT @insertedId = SCOPE_IDENTITY();`;
93
+ const result = await request.query(updatedQuery);
94
+ lastID = result.output.insertedId || 0;
95
+ }
96
+ else {
97
+ const result = await request.query(preparedQuery);
98
+ lastID = 0;
99
+ }
100
+ return {
101
+ changes: this.getAffectedRows(query, lastID),
102
+ lastID: lastID
103
+ };
104
+ }
105
+ catch (err) {
106
+ throw new Error(`SQL Server query error: ${err.message}`);
107
+ }
108
+ }
109
+ /**
110
+ * Execute multiple SQL statements
111
+ * @param query SQL statements to execute
112
+ * @returns Promise that resolves when execution completes
113
+ */
114
+ async exec(query) {
115
+ if (!this.pool) {
116
+ throw new Error("Database not initialized");
117
+ }
118
+ try {
119
+ const request = this.pool.request();
120
+ await request.batch(query);
121
+ }
122
+ catch (err) {
123
+ throw new Error(`SQL Server batch error: ${err.message}`);
124
+ }
125
+ }
126
+ /**
127
+ * Close the database connection
128
+ */
129
+ async close() {
130
+ if (this.pool) {
131
+ await this.pool.close();
132
+ this.pool = null;
133
+ }
134
+ }
135
+ /**
136
+ * Get database metadata
137
+ */
138
+ getMetadata() {
139
+ return {
140
+ name: "SQL Server",
141
+ type: "sqlserver",
142
+ server: this.server,
143
+ database: this.database
144
+ };
145
+ }
146
+ /**
147
+ * Get database-specific query for listing tables
148
+ */
149
+ getListTablesQuery() {
150
+ return "SELECT TABLE_NAME as name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME";
151
+ }
152
+ /**
153
+ * Get database-specific query for describing a table
154
+ * @param tableName Table name
155
+ */
156
+ getDescribeTableQuery(tableName) {
157
+ return `
158
+ SELECT
159
+ c.COLUMN_NAME as name,
160
+ c.DATA_TYPE as type,
161
+ CASE WHEN c.IS_NULLABLE = 'NO' THEN 1 ELSE 0 END as notnull,
162
+ CASE WHEN pk.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1 ELSE 0 END as pk,
163
+ c.COLUMN_DEFAULT as dflt_value
164
+ FROM
165
+ INFORMATION_SCHEMA.COLUMNS c
166
+ LEFT JOIN
167
+ INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON c.TABLE_NAME = kcu.TABLE_NAME AND c.COLUMN_NAME = kcu.COLUMN_NAME
168
+ LEFT JOIN
169
+ INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ON kcu.CONSTRAINT_NAME = pk.CONSTRAINT_NAME AND pk.CONSTRAINT_TYPE = 'PRIMARY KEY'
170
+ WHERE
171
+ c.TABLE_NAME = '${tableName}'
172
+ ORDER BY
173
+ c.ORDINAL_POSITION
174
+ `;
175
+ }
176
+ /**
177
+ * Helper to get the number of affected rows based on query type
178
+ */
179
+ getAffectedRows(query, lastID) {
180
+ const queryType = query.trim().split(' ')[0].toUpperCase();
181
+ if (queryType === 'INSERT' && lastID > 0) {
182
+ return 1;
183
+ }
184
+ return 0; // For SELECT, unknown for UPDATE/DELETE without additional query
185
+ }
186
+ }
@@ -0,0 +1,71 @@
1
+ import { dbAll, getListTablesQuery, getDescribeTableQuery, getDatabaseMetadata } from '../db/index.js';
2
+ /**
3
+ * Handle listing resources request
4
+ * @returns List of available resources
5
+ */
6
+ export async function handleListResources() {
7
+ try {
8
+ const dbInfo = getDatabaseMetadata();
9
+ const dbType = dbInfo.type;
10
+ let resourceBaseUrl;
11
+ // Create appropriate URL based on database type
12
+ if (dbType === 'sqlite' && dbInfo.path) {
13
+ resourceBaseUrl = new URL(`sqlite:///${dbInfo.path}`);
14
+ }
15
+ else if (dbType === 'sqlserver' && dbInfo.server && dbInfo.database) {
16
+ resourceBaseUrl = new URL(`sqlserver://${dbInfo.server}/${dbInfo.database}`);
17
+ }
18
+ else {
19
+ resourceBaseUrl = new URL(`db:///database`);
20
+ }
21
+ const SCHEMA_PATH = "schema";
22
+ // Use adapter-specific query to list tables
23
+ const query = getListTablesQuery();
24
+ const result = await dbAll(query);
25
+ return {
26
+ resources: result.map((row) => ({
27
+ uri: new URL(`${row.name}/${SCHEMA_PATH}`, resourceBaseUrl).href,
28
+ mimeType: "application/json",
29
+ name: `"${row.name}" database schema`,
30
+ })),
31
+ };
32
+ }
33
+ catch (error) {
34
+ throw new Error(`Error listing resources: ${error.message}`);
35
+ }
36
+ }
37
+ /**
38
+ * Handle reading a specific resource
39
+ * @param uri URI of the resource to read
40
+ * @returns Resource contents
41
+ */
42
+ export async function handleReadResource(uri) {
43
+ try {
44
+ const resourceUrl = new URL(uri);
45
+ const SCHEMA_PATH = "schema";
46
+ const pathComponents = resourceUrl.pathname.split("/");
47
+ const schema = pathComponents.pop();
48
+ const tableName = pathComponents.pop();
49
+ if (schema !== SCHEMA_PATH) {
50
+ throw new Error("Invalid resource URI");
51
+ }
52
+ // Use adapter-specific query to describe the table
53
+ const query = getDescribeTableQuery(tableName);
54
+ const result = await dbAll(query);
55
+ return {
56
+ contents: [
57
+ {
58
+ uri,
59
+ mimeType: "application/json",
60
+ text: JSON.stringify(result.map((column) => ({
61
+ column_name: column.name,
62
+ data_type: column.type
63
+ })), null, 2),
64
+ },
65
+ ],
66
+ };
67
+ }
68
+ catch (error) {
69
+ throw new Error(`Error reading resource: ${error.message}`);
70
+ }
71
+ }
@@ -0,0 +1,158 @@
1
+ import { formatErrorResponse } from '../utils/formatUtils.js';
2
+ // Import all tool implementations
3
+ import { readQuery, writeQuery, exportQuery } from '../tools/queryTools.js';
4
+ import { createTable, alterTable, dropTable, listTables, describeTable } from '../tools/schemaTools.js';
5
+ import { appendInsight, listInsights } from '../tools/insightTools.js';
6
+ /**
7
+ * Handle listing available tools
8
+ * @returns List of available tools
9
+ */
10
+ export function handleListTools() {
11
+ return {
12
+ tools: [
13
+ {
14
+ name: "read_query",
15
+ description: "Execute SELECT queries to read data from the database",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ query: { type: "string" },
20
+ },
21
+ required: ["query"],
22
+ },
23
+ },
24
+ {
25
+ name: "write_query",
26
+ description: "Execute INSERT, UPDATE, or DELETE queries",
27
+ inputSchema: {
28
+ type: "object",
29
+ properties: {
30
+ query: { type: "string" },
31
+ },
32
+ required: ["query"],
33
+ },
34
+ },
35
+ {
36
+ name: "create_table",
37
+ description: "Create new tables in the database",
38
+ inputSchema: {
39
+ type: "object",
40
+ properties: {
41
+ query: { type: "string" },
42
+ },
43
+ required: ["query"],
44
+ },
45
+ },
46
+ {
47
+ name: "alter_table",
48
+ description: "Modify existing table schema (add columns, rename tables, etc.)",
49
+ inputSchema: {
50
+ type: "object",
51
+ properties: {
52
+ query: { type: "string" },
53
+ },
54
+ required: ["query"],
55
+ },
56
+ },
57
+ {
58
+ name: "drop_table",
59
+ description: "Remove a table from the database with safety confirmation",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: {
63
+ table_name: { type: "string" },
64
+ confirm: { type: "boolean" },
65
+ },
66
+ required: ["table_name", "confirm"],
67
+ },
68
+ },
69
+ {
70
+ name: "export_query",
71
+ description: "Export query results to various formats (CSV, JSON)",
72
+ inputSchema: {
73
+ type: "object",
74
+ properties: {
75
+ query: { type: "string" },
76
+ format: { type: "string", enum: ["csv", "json"] },
77
+ },
78
+ required: ["query", "format"],
79
+ },
80
+ },
81
+ {
82
+ name: "list_tables",
83
+ description: "Get a list of all tables in the database",
84
+ inputSchema: {
85
+ type: "object",
86
+ properties: {},
87
+ },
88
+ },
89
+ {
90
+ name: "describe_table",
91
+ description: "View schema information for a specific table",
92
+ inputSchema: {
93
+ type: "object",
94
+ properties: {
95
+ table_name: { type: "string" },
96
+ },
97
+ required: ["table_name"],
98
+ },
99
+ },
100
+ {
101
+ name: "append_insight",
102
+ description: "Add a business insight to the memo",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {
106
+ insight: { type: "string" },
107
+ },
108
+ required: ["insight"],
109
+ },
110
+ },
111
+ {
112
+ name: "list_insights",
113
+ description: "List all business insights in the memo",
114
+ inputSchema: {
115
+ type: "object",
116
+ properties: {},
117
+ },
118
+ },
119
+ ],
120
+ };
121
+ }
122
+ /**
123
+ * Handle tool call requests
124
+ * @param name Name of the tool to call
125
+ * @param args Arguments for the tool
126
+ * @returns Tool execution result
127
+ */
128
+ export async function handleToolCall(name, args) {
129
+ try {
130
+ switch (name) {
131
+ case "read_query":
132
+ return await readQuery(args.query);
133
+ case "write_query":
134
+ return await writeQuery(args.query);
135
+ case "create_table":
136
+ return await createTable(args.query);
137
+ case "alter_table":
138
+ return await alterTable(args.query);
139
+ case "drop_table":
140
+ return await dropTable(args.table_name, args.confirm);
141
+ case "export_query":
142
+ return await exportQuery(args.query, args.format);
143
+ case "list_tables":
144
+ return await listTables();
145
+ case "describe_table":
146
+ return await describeTable(args.table_name);
147
+ case "append_insight":
148
+ return await appendInsight(args.insight);
149
+ case "list_insights":
150
+ return await listInsights();
151
+ default:
152
+ throw new Error(`Unknown tool: ${name}`);
153
+ }
154
+ }
155
+ catch (error) {
156
+ return formatErrorResponse(error);
157
+ }
158
+ }
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ // Import database utils
6
+ import { initDatabase, closeDatabase, getDatabaseMetadata } from './db/index.js';
7
+ // Import handlers
8
+ import { handleListResources, handleReadResource } from './handlers/resourceHandlers.js';
9
+ import { handleListTools, handleToolCall } from './handlers/toolHandlers.js';
10
+ // Setup a logger that uses stderr instead of stdout to avoid interfering with MCP communications
11
+ const logger = {
12
+ log: (...args) => console.error('[INFO]', ...args),
13
+ error: (...args) => console.error('[ERROR]', ...args),
14
+ warn: (...args) => console.error('[WARN]', ...args),
15
+ info: (...args) => console.error('[INFO]', ...args),
16
+ };
17
+ // Configure the server
18
+ const server = new Server({
19
+ name: "executeautomation/database-server",
20
+ version: "1.1.0",
21
+ }, {
22
+ capabilities: {
23
+ resources: {},
24
+ tools: {},
25
+ },
26
+ });
27
+ // Parse command line arguments
28
+ const args = process.argv.slice(2);
29
+ if (args.length === 0) {
30
+ logger.error("Please provide database connection information");
31
+ logger.error("Usage for SQLite: node index.js <database_file_path>");
32
+ logger.error("Usage for SQL Server: node index.js --sqlserver --server <server> --database <database> [--user <user> --password <password>]");
33
+ logger.error("Usage for PostgreSQL: node index.js --postgresql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
34
+ logger.error("Usage for MySQL: node index.js --mysql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
35
+ logger.error("Usage for MySQL with AWS IAM: node index.js --mysql --aws-iam-auth --host <rds-endpoint> --database <database> --user <aws-username> --aws-region <region>");
36
+ process.exit(1);
37
+ }
38
+ // Parse arguments to determine database type and connection info
39
+ let dbType = 'sqlite';
40
+ let connectionInfo = null;
41
+ // Check if using SQL Server
42
+ if (args.includes('--sqlserver')) {
43
+ dbType = 'sqlserver';
44
+ connectionInfo = {
45
+ server: '',
46
+ database: '',
47
+ user: undefined,
48
+ password: undefined
49
+ };
50
+ // Parse SQL Server connection parameters
51
+ for (let i = 0; i < args.length; i++) {
52
+ if (args[i] === '--server' && i + 1 < args.length) {
53
+ connectionInfo.server = args[i + 1];
54
+ }
55
+ else if (args[i] === '--database' && i + 1 < args.length) {
56
+ connectionInfo.database = args[i + 1];
57
+ }
58
+ else if (args[i] === '--user' && i + 1 < args.length) {
59
+ connectionInfo.user = args[i + 1];
60
+ }
61
+ else if (args[i] === '--password' && i + 1 < args.length) {
62
+ connectionInfo.password = args[i + 1];
63
+ }
64
+ else if (args[i] === '--port' && i + 1 < args.length) {
65
+ connectionInfo.port = parseInt(args[i + 1], 10);
66
+ }
67
+ }
68
+ // Validate SQL Server connection info
69
+ if (!connectionInfo.server || !connectionInfo.database) {
70
+ logger.error("Error: SQL Server requires --server and --database parameters");
71
+ process.exit(1);
72
+ }
73
+ }
74
+ // Check if using PostgreSQL
75
+ else if (args.includes('--postgresql') || args.includes('--postgres')) {
76
+ dbType = 'postgresql';
77
+ connectionInfo = {
78
+ host: '',
79
+ database: '',
80
+ user: undefined,
81
+ password: undefined,
82
+ port: undefined,
83
+ ssl: undefined,
84
+ connectionTimeout: undefined
85
+ };
86
+ // Parse PostgreSQL connection parameters
87
+ for (let i = 0; i < args.length; i++) {
88
+ if (args[i] === '--host' && i + 1 < args.length) {
89
+ connectionInfo.host = args[i + 1];
90
+ }
91
+ else if (args[i] === '--database' && i + 1 < args.length) {
92
+ connectionInfo.database = args[i + 1];
93
+ }
94
+ else if (args[i] === '--user' && i + 1 < args.length) {
95
+ connectionInfo.user = args[i + 1];
96
+ }
97
+ else if (args[i] === '--password' && i + 1 < args.length) {
98
+ connectionInfo.password = args[i + 1];
99
+ }
100
+ else if (args[i] === '--port' && i + 1 < args.length) {
101
+ connectionInfo.port = parseInt(args[i + 1], 10);
102
+ }
103
+ else if (args[i] === '--ssl' && i + 1 < args.length) {
104
+ connectionInfo.ssl = args[i + 1] === 'true';
105
+ }
106
+ else if (args[i] === '--connection-timeout' && i + 1 < args.length) {
107
+ connectionInfo.connectionTimeout = parseInt(args[i + 1], 10);
108
+ }
109
+ }
110
+ // Validate PostgreSQL connection info
111
+ if (!connectionInfo.host || !connectionInfo.database) {
112
+ logger.error("Error: PostgreSQL requires --host and --database parameters");
113
+ process.exit(1);
114
+ }
115
+ }
116
+ // Check if using MySQL
117
+ else if (args.includes('--mysql')) {
118
+ dbType = 'mysql';
119
+ connectionInfo = {
120
+ host: '',
121
+ database: '',
122
+ user: undefined,
123
+ password: undefined,
124
+ port: undefined,
125
+ ssl: undefined,
126
+ connectionTimeout: undefined,
127
+ awsIamAuth: false,
128
+ awsRegion: undefined
129
+ };
130
+ // Parse MySQL connection parameters
131
+ for (let i = 0; i < args.length; i++) {
132
+ if (args[i] === '--host' && i + 1 < args.length) {
133
+ connectionInfo.host = args[i + 1];
134
+ }
135
+ else if (args[i] === '--database' && i + 1 < args.length) {
136
+ connectionInfo.database = args[i + 1];
137
+ }
138
+ else if (args[i] === '--user' && i + 1 < args.length) {
139
+ connectionInfo.user = args[i + 1];
140
+ }
141
+ else if (args[i] === '--password' && i + 1 < args.length) {
142
+ connectionInfo.password = args[i + 1];
143
+ }
144
+ else if (args[i] === '--port' && i + 1 < args.length) {
145
+ connectionInfo.port = parseInt(args[i + 1], 10);
146
+ }
147
+ else if (args[i] === '--ssl' && i + 1 < args.length) {
148
+ const sslVal = args[i + 1];
149
+ if (sslVal === 'true')
150
+ connectionInfo.ssl = true;
151
+ else if (sslVal === 'false')
152
+ connectionInfo.ssl = false;
153
+ else
154
+ connectionInfo.ssl = sslVal;
155
+ }
156
+ else if (args[i] === '--connection-timeout' && i + 1 < args.length) {
157
+ connectionInfo.connectionTimeout = parseInt(args[i + 1], 10);
158
+ }
159
+ else if (args[i] === '--aws-iam-auth') {
160
+ connectionInfo.awsIamAuth = true;
161
+ }
162
+ else if (args[i] === '--aws-region' && i + 1 < args.length) {
163
+ connectionInfo.awsRegion = args[i + 1];
164
+ }
165
+ }
166
+ // Validate MySQL connection info
167
+ if (!connectionInfo.host || !connectionInfo.database) {
168
+ logger.error("Error: MySQL requires --host and --database parameters");
169
+ process.exit(1);
170
+ }
171
+ // Additional validation for AWS IAM authentication
172
+ if (connectionInfo.awsIamAuth) {
173
+ if (!connectionInfo.user) {
174
+ logger.error("Error: AWS IAM authentication requires --user parameter");
175
+ process.exit(1);
176
+ }
177
+ if (!connectionInfo.awsRegion) {
178
+ logger.error("Error: AWS IAM authentication requires --aws-region parameter");
179
+ process.exit(1);
180
+ }
181
+ // Automatically enable SSL for AWS IAM authentication (required)
182
+ connectionInfo.ssl = true;
183
+ logger.info("AWS IAM authentication enabled - SSL automatically configured");
184
+ }
185
+ }
186
+ else {
187
+ // SQLite mode (default)
188
+ dbType = 'sqlite';
189
+ connectionInfo = args[0]; // First argument is the SQLite file path
190
+ logger.info(`Using SQLite database at path: ${connectionInfo}`);
191
+ }
192
+ // Set up request handlers
193
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
194
+ return await handleListResources();
195
+ });
196
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
197
+ return await handleReadResource(request.params.uri);
198
+ });
199
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
200
+ return handleListTools();
201
+ });
202
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
203
+ return await handleToolCall(request.params.name, request.params.arguments);
204
+ });
205
+ // Handle shutdown gracefully
206
+ process.on('SIGINT', async () => {
207
+ logger.info('Shutting down gracefully...');
208
+ await closeDatabase();
209
+ process.exit(0);
210
+ });
211
+ process.on('SIGTERM', async () => {
212
+ logger.info('Shutting down gracefully...');
213
+ await closeDatabase();
214
+ process.exit(0);
215
+ });
216
+ // Add global error handler
217
+ process.on('uncaughtException', (error) => {
218
+ logger.error('Uncaught exception:', error);
219
+ });
220
+ process.on('unhandledRejection', (reason, promise) => {
221
+ logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
222
+ });
223
+ /**
224
+ * Start the server
225
+ */
226
+ async function runServer() {
227
+ try {
228
+ logger.info(`Initializing ${dbType} database...`);
229
+ if (dbType === 'sqlite') {
230
+ logger.info(`Database path: ${connectionInfo}`);
231
+ }
232
+ else if (dbType === 'sqlserver') {
233
+ logger.info(`Server: ${connectionInfo.server}, Database: ${connectionInfo.database}`);
234
+ }
235
+ else if (dbType === 'postgresql') {
236
+ logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`);
237
+ }
238
+ else if (dbType === 'mysql') {
239
+ logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`);
240
+ }
241
+ // Initialize the database
242
+ await initDatabase(connectionInfo, dbType);
243
+ const dbInfo = getDatabaseMetadata();
244
+ logger.info(`Connected to ${dbInfo.name} database`);
245
+ logger.info('Starting MCP server...');
246
+ const transport = new StdioServerTransport();
247
+ await server.connect(transport);
248
+ logger.info('Server running. Press Ctrl+C to exit.');
249
+ }
250
+ catch (error) {
251
+ logger.error("Failed to initialize:", error);
252
+ process.exit(1);
253
+ }
254
+ }
255
+ // Start the server
256
+ runServer().catch(error => {
257
+ logger.error("Server initialization failed:", error);
258
+ process.exit(1);
259
+ });