@tejasanik/postgres-mcp-server 1.5.0 → 1.6.0

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 CHANGED
@@ -1,418 +1,295 @@
1
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, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
- import { resetDbManager } from './db-manager.js';
6
- import { listServersAndDbs, switchServerDb, getCurrentConnection, listSchemas, listObjects, getObjectDetails, executeSql, explainQuery, getTopQueries, analyzeWorkloadIndexes, analyzeQueryIndexes, analyzeDbHealth } from './tools/index.js';
7
- // Tool definitions
8
- const tools = [
9
- {
10
- name: 'list_servers_and_dbs',
11
- description: 'Lists all configured PostgreSQL servers and their databases. Use fetchDatabases=true to list databases. Use searchAllServers=true to fetch databases from all servers (not just the connected one).',
12
- inputSchema: {
13
- type: 'object',
14
- properties: {
15
- serverFilter: {
16
- type: 'string',
17
- description: 'Filter servers by name or host (case-insensitive partial match)'
18
- },
19
- databaseFilter: {
20
- type: 'string',
21
- description: 'Filter databases by name (case-insensitive partial match)'
22
- },
23
- includeSystemDbs: {
24
- type: 'boolean',
25
- description: 'Include system databases (template0, template1)',
26
- default: false
27
- },
28
- fetchDatabases: {
29
- type: 'boolean',
30
- description: 'Fetch list of databases from servers',
31
- default: false
32
- },
33
- searchAllServers: {
34
- type: 'boolean',
35
- description: 'When true, fetch databases from all configured servers (temporarily connects to each). When false, only fetch from currently connected server.',
36
- default: false
37
- }
38
- }
39
- }
40
- },
41
- {
42
- name: 'switch_server_db',
43
- description: 'Switch to a different PostgreSQL server and optionally a specific database and schema. Must be called before using other database tools. Uses server defaults if not specified.',
44
- inputSchema: {
45
- type: 'object',
46
- properties: {
47
- server: {
48
- type: 'string',
49
- description: 'Name of the server to connect to (from POSTGRES_SERVERS config)'
50
- },
51
- database: {
52
- type: 'string',
53
- description: 'Name of the database to connect to (uses server default or "postgres")'
54
- },
55
- schema: {
56
- type: 'string',
57
- description: 'Name of the default schema (uses server default or "public")'
58
- }
59
- },
60
- required: ['server']
61
- }
62
- },
63
- {
64
- name: 'get_current_connection',
65
- description: 'Returns details about the current database connection including server, database, schema, host, port, and access mode (readonly/full).',
66
- inputSchema: {
67
- type: 'object',
68
- properties: {}
69
- }
70
- },
71
- {
72
- name: 'list_schemas',
73
- description: 'Lists all database schemas available in the current PostgreSQL database.',
74
- inputSchema: {
75
- type: 'object',
76
- properties: {
77
- includeSystemSchemas: {
78
- type: 'boolean',
79
- description: 'Include system schemas (pg_catalog, information_schema, etc.)',
80
- default: false
81
- }
82
- }
83
- }
84
- },
85
- {
86
- name: 'list_objects',
87
- description: 'Lists database objects (tables, views, sequences, extensions) within a specified schema.',
88
- inputSchema: {
89
- type: 'object',
90
- properties: {
91
- schema: {
92
- type: 'string',
93
- description: 'Schema name to list objects from'
94
- },
95
- objectType: {
96
- type: 'string',
97
- enum: ['table', 'view', 'sequence', 'extension', 'all'],
98
- description: 'Type of objects to list',
99
- default: 'all'
100
- },
101
- filter: {
102
- type: 'string',
103
- description: 'Filter objects by name (case-insensitive partial match)'
104
- }
105
- },
106
- required: ['schema']
107
- }
108
- },
109
- {
110
- name: 'get_object_details',
111
- description: 'Provides detailed information about a specific database object including columns, constraints, indexes, size, and row count.',
112
- inputSchema: {
113
- type: 'object',
114
- properties: {
115
- schema: {
116
- type: 'string',
117
- description: 'Schema name containing the object'
118
- },
119
- objectName: {
120
- type: 'string',
121
- description: 'Name of the object to get details for'
122
- },
123
- objectType: {
124
- type: 'string',
125
- enum: ['table', 'view', 'sequence'],
126
- description: 'Type of the object'
127
- }
128
- },
129
- required: ['schema', 'objectName']
130
- }
131
- },
132
- {
133
- name: 'execute_sql',
134
- description: 'Executes SQL statements on the database. Supports pagination with offset/maxRows. Returns execution time. Use params for parameterized queries (e.g., sql: "SELECT * FROM users WHERE id = $1", params: [123]). Read-only mode prevents write operations.',
135
- inputSchema: {
136
- type: 'object',
137
- properties: {
138
- sql: {
139
- type: 'string',
140
- description: 'SQL statement to execute. Use $1, $2, etc. for parameterized queries.'
141
- },
142
- params: {
143
- type: 'array',
144
- description: 'Parameters for parameterized queries (e.g., [123, "value"]). Prevents SQL injection.',
145
- items: {}
146
- },
147
- maxRows: {
148
- type: 'number',
149
- description: 'Maximum rows to return (default: 1000, max: 100000). Use with offset for pagination.',
150
- default: 1000
151
- },
152
- offset: {
153
- type: 'number',
154
- description: 'Number of rows to skip (for pagination). Use with maxRows to paginate through large results.',
155
- default: 0
156
- },
157
- allowLargeScript: {
158
- type: 'boolean',
159
- description: 'Set to true to bypass the 100KB SQL length limit for large deployment scripts.',
160
- default: false
161
- }
162
- },
163
- required: ['sql']
164
- }
165
- },
166
- {
167
- name: 'explain_query',
168
- description: 'Gets the execution plan for a SQL query, showing how PostgreSQL will process it. Can simulate hypothetical indexes if hypopg extension is installed.',
169
- inputSchema: {
170
- type: 'object',
171
- properties: {
172
- sql: {
173
- type: 'string',
174
- description: 'SQL query to explain'
175
- },
176
- analyze: {
177
- type: 'boolean',
178
- description: 'Actually execute the query to get real timing (default: false). Only allowed for SELECT queries.',
179
- default: false
180
- },
181
- buffers: {
182
- type: 'boolean',
183
- description: 'Include buffer usage statistics',
184
- default: false
185
- },
186
- format: {
187
- type: 'string',
188
- enum: ['text', 'json', 'yaml', 'xml'],
189
- description: 'Output format for the plan',
190
- default: 'json'
191
- },
192
- hypotheticalIndexes: {
193
- type: 'array',
194
- description: 'Hypothetical indexes to simulate (requires hypopg extension)',
195
- items: {
196
- type: 'object',
197
- properties: {
198
- table: {
199
- type: 'string',
200
- description: 'Table name for the hypothetical index'
201
- },
202
- columns: {
203
- type: 'array',
204
- items: { type: 'string' },
205
- description: 'Columns to include in the index'
206
- },
207
- indexType: {
208
- type: 'string',
209
- description: 'Index type (btree, hash, gist, etc.)',
210
- default: 'btree'
211
- }
212
- },
213
- required: ['table', 'columns']
214
- }
215
- }
216
- },
217
- required: ['sql']
218
- }
219
- },
220
- {
221
- name: 'get_top_queries',
222
- description: 'Reports the slowest SQL queries based on total execution time using pg_stat_statements data. Requires pg_stat_statements extension.',
223
- inputSchema: {
224
- type: 'object',
225
- properties: {
226
- limit: {
227
- type: 'number',
228
- description: 'Number of queries to return (1-100)',
229
- default: 10
230
- },
231
- orderBy: {
232
- type: 'string',
233
- enum: ['total_time', 'mean_time', 'calls'],
234
- description: 'How to order the results',
235
- default: 'total_time'
236
- },
237
- minCalls: {
238
- type: 'number',
239
- description: 'Minimum number of calls to include a query',
240
- default: 1
241
- }
242
- }
243
- }
244
- },
245
- {
246
- name: 'analyze_workload_indexes',
247
- description: 'Analyzes the database workload (using pg_stat_statements) to identify resource-intensive queries and recommends optimal indexes for them.',
248
- inputSchema: {
249
- type: 'object',
250
- properties: {
251
- topQueriesCount: {
252
- type: 'number',
253
- description: 'Number of top queries to analyze (1-50)',
254
- default: 20
255
- },
256
- includeHypothetical: {
257
- type: 'boolean',
258
- description: 'Include hypothetical index analysis (requires hypopg)',
259
- default: false
260
- }
261
- }
262
- }
263
- },
264
- {
265
- name: 'analyze_query_indexes',
266
- description: 'Analyzes specific SQL queries (up to 10) and recommends optimal indexes for them.',
267
- inputSchema: {
268
- type: 'object',
269
- properties: {
270
- queries: {
271
- type: 'array',
272
- items: { type: 'string' },
273
- description: 'List of SQL queries to analyze (max 10)',
274
- maxItems: 10
275
- }
276
- },
277
- required: ['queries']
278
- }
279
- },
280
- {
281
- name: 'analyze_db_health',
282
- description: 'Performs comprehensive database health checks including: buffer cache hit rates, connection health, constraint validation, index health (duplicate/unused/invalid), sequence limits, and vacuum health.',
283
- inputSchema: {
284
- type: 'object',
285
- properties: {}
286
- }
287
- }
288
- ];
289
- // Create MCP server
290
- const server = new Server({
291
- name: 'postgres-mcp-server',
292
- version: '1.0.0',
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { resetDbManager } from "./db-manager.js";
6
+ import { listServers, listDatabases, switchServerDb, getCurrentConnection, listSchemas, listObjects, getObjectDetails, executeSql, explainQuery, getTopQueries, analyzeWorkloadIndexes, analyzeQueryIndexes, analyzeDbHealth, } from "./tools/index.js";
7
+ // Create MCP server using the new high-level API
8
+ const server = new McpServer({
9
+ name: "postgres-mcp-server",
10
+ version: "1.6.0",
293
11
  }, {
294
12
  capabilities: {
295
13
  tools: {},
296
14
  },
297
15
  });
298
- // Handle list_tools request
299
- server.setRequestHandler(ListToolsRequestSchema, async () => {
300
- return { tools };
16
+ // Register tools with improved descriptions
17
+ server.registerTool("list_servers", {
18
+ description: "List all configured PostgreSQL servers. Call this FIRST to discover available server names before using list_databases or switch_server_db. Returns server names, hosts, ports, and connection status.",
19
+ inputSchema: z.object({
20
+ filter: z
21
+ .string()
22
+ .optional()
23
+ .describe("Filter servers by name or host (case-insensitive partial match)"),
24
+ }),
25
+ }, async (args) => {
26
+ const result = await listServers(args);
27
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
301
28
  });
302
- // Handle tool calls
303
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
304
- const { name, arguments: args } = request.params;
305
- try {
306
- let result;
307
- switch (name) {
308
- case 'list_servers_and_dbs':
309
- result = await listServersAndDbs(args);
310
- break;
311
- case 'switch_server_db':
312
- result = await switchServerDb(args);
313
- break;
314
- case 'get_current_connection':
315
- result = await getCurrentConnection();
316
- break;
317
- case 'list_schemas':
318
- result = await listSchemas(args);
319
- break;
320
- case 'list_objects':
321
- result = await listObjects(args);
322
- break;
323
- case 'get_object_details':
324
- result = await getObjectDetails(args);
325
- break;
326
- case 'execute_sql':
327
- result = await executeSql(args);
328
- // Special handling for large output
329
- if (result.outputFile) {
330
- return {
331
- content: [
332
- {
333
- type: 'text',
334
- text: JSON.stringify({
335
- message: `Output too large (${result.rowCount} rows). Results written to file.`,
336
- outputFile: result.outputFile,
337
- rowCount: result.rowCount,
338
- fields: result.fields,
339
- hint: 'Read the file optimally using offset/limit or run the query with filters to reduce output.'
340
- }, null, 2)
341
- }
342
- ]
343
- };
344
- }
345
- break;
346
- case 'explain_query':
347
- result = await explainQuery(args);
348
- break;
349
- case 'get_top_queries':
350
- result = await getTopQueries(args);
351
- break;
352
- case 'analyze_workload_indexes':
353
- result = await analyzeWorkloadIndexes(args);
354
- break;
355
- case 'analyze_query_indexes':
356
- result = await analyzeQueryIndexes(args);
357
- break;
358
- case 'analyze_db_health':
359
- result = await analyzeDbHealth();
360
- break;
361
- default:
362
- throw new Error(`Unknown tool: ${name}`);
363
- }
364
- return {
365
- content: [
366
- {
367
- type: 'text',
368
- text: JSON.stringify(result, null, 2)
369
- }
370
- ]
371
- };
372
- }
373
- catch (error) {
374
- const errorMessage = error instanceof Error ? error.message : String(error);
29
+ server.registerTool("list_databases", {
30
+ description: "List databases in a specific PostgreSQL server. REQUIRES serverName parameter - use list_servers first to get valid server names. Do NOT guess server names.",
31
+ inputSchema: z.object({
32
+ serverName: z
33
+ .string()
34
+ .describe("REQUIRED: Server name from list_servers. Do NOT use database names here."),
35
+ filter: z
36
+ .string()
37
+ .optional()
38
+ .describe("Filter databases by name (case-insensitive partial match)"),
39
+ includeSystemDbs: z
40
+ .boolean()
41
+ .optional()
42
+ .default(false)
43
+ .describe("Include system databases (template0, template1)"),
44
+ maxResults: z
45
+ .number()
46
+ .optional()
47
+ .default(50)
48
+ .describe("Maximum databases to return (default: 50, max: 200)"),
49
+ }),
50
+ }, async (args) => {
51
+ const result = await listDatabases(args);
52
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
53
+ });
54
+ server.registerTool("switch_server_db", {
55
+ description: "Connect to a PostgreSQL server and database. MUST be called before executing queries. Use list_servers to find server names, list_databases to find database names.",
56
+ inputSchema: z.object({
57
+ server: z.string().describe("Server name from list_servers (NOT the host)"),
58
+ database: z
59
+ .string()
60
+ .optional()
61
+ .describe("Database name from list_databases (defaults to server's default or 'postgres')"),
62
+ schema: z
63
+ .string()
64
+ .optional()
65
+ .describe("Schema name (defaults to 'public')"),
66
+ }),
67
+ }, async (args) => {
68
+ const result = await switchServerDb(args);
69
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
70
+ });
71
+ server.registerTool("get_current_connection", {
72
+ description: "Get current connection status. Returns server, database, schema, host, port, and access mode (readonly/full). Call this to verify your connection before running queries.",
73
+ inputSchema: z.object({}),
74
+ }, async () => {
75
+ const result = await getCurrentConnection();
76
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
77
+ });
78
+ server.registerTool("list_schemas", {
79
+ description: "List all schemas in the current database. Requires active connection (use switch_server_db first).",
80
+ inputSchema: z.object({
81
+ includeSystemSchemas: z
82
+ .boolean()
83
+ .optional()
84
+ .default(false)
85
+ .describe("Include system schemas (pg_catalog, information_schema, etc.)"),
86
+ }),
87
+ }, async (args) => {
88
+ const result = await listSchemas(args);
89
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
90
+ });
91
+ server.registerTool("list_objects", {
92
+ description: "List tables, views, sequences, or extensions in a schema. Requires active connection.",
93
+ inputSchema: z.object({
94
+ schema: z.string().describe("Schema name (e.g., 'public')"),
95
+ objectType: z
96
+ .enum(["table", "view", "sequence", "extension", "all"])
97
+ .optional()
98
+ .default("all")
99
+ .describe("Type of objects to list"),
100
+ filter: z
101
+ .string()
102
+ .optional()
103
+ .describe("Filter objects by name (case-insensitive partial match)"),
104
+ }),
105
+ }, async (args) => {
106
+ const result = await listObjects(args);
107
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
108
+ });
109
+ server.registerTool("get_object_details", {
110
+ description: "Get detailed info about a table/view/sequence: columns, data types, constraints, indexes, size, row count. Use this to understand table structure before writing queries.",
111
+ inputSchema: z.object({
112
+ schema: z.string().describe("Schema name containing the object"),
113
+ objectName: z.string().describe("Name of the table, view, or sequence"),
114
+ objectType: z
115
+ .enum(["table", "view", "sequence"])
116
+ .optional()
117
+ .describe("Object type (auto-detected if not specified)"),
118
+ }),
119
+ }, async (args) => {
120
+ const result = await getObjectDetails(args);
121
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
122
+ });
123
+ server.registerTool("execute_sql", {
124
+ description: "Execute SQL queries. Supports SELECT, INSERT, UPDATE, DELETE (if not in readonly mode). Use $1, $2 placeholders with params array to prevent SQL injection. Returns rows, execution time, and pagination info.",
125
+ inputSchema: z.object({
126
+ sql: z
127
+ .string()
128
+ .describe("SQL statement. Use $1, $2, etc. for parameterized queries."),
129
+ params: z
130
+ .array(z.any())
131
+ .optional()
132
+ .describe("Parameters for $1, $2, etc. placeholders (e.g., [123, 'value'])"),
133
+ maxRows: z
134
+ .number()
135
+ .optional()
136
+ .default(1000)
137
+ .describe("Max rows to return (default: 1000, max: 100000)"),
138
+ offset: z
139
+ .number()
140
+ .optional()
141
+ .default(0)
142
+ .describe("Skip rows for pagination"),
143
+ allowLargeScript: z
144
+ .boolean()
145
+ .optional()
146
+ .default(false)
147
+ .describe("Bypass 100KB SQL limit for deployment scripts"),
148
+ }),
149
+ }, async (args) => {
150
+ const result = await executeSql(args);
151
+ // Special handling for large output
152
+ if (result.outputFile) {
375
153
  return {
376
154
  content: [
377
155
  {
378
- type: 'text',
379
- text: JSON.stringify({ error: errorMessage }, null, 2)
380
- }
156
+ type: "text",
157
+ text: JSON.stringify({
158
+ message: `Output too large (${result.rowCount} rows). Results written to file.`,
159
+ outputFile: result.outputFile,
160
+ rowCount: result.rowCount,
161
+ fields: result.fields,
162
+ hint: "Use offset/maxRows to paginate, or add WHERE clauses to reduce results.",
163
+ }, null, 2),
164
+ },
381
165
  ],
382
- isError: true
383
166
  };
384
167
  }
168
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
169
+ });
170
+ server.registerTool("explain_query", {
171
+ description: "Show PostgreSQL's execution plan for a query. Use this to understand query performance and identify missing indexes. analyze=true runs the query to get actual timings (SELECT only).",
172
+ inputSchema: z.object({
173
+ sql: z.string().describe("SQL query to explain"),
174
+ analyze: z
175
+ .boolean()
176
+ .optional()
177
+ .default(false)
178
+ .describe("Execute query for real timing (SELECT only, blocked for writes)"),
179
+ buffers: z
180
+ .boolean()
181
+ .optional()
182
+ .default(false)
183
+ .describe("Include buffer/cache statistics"),
184
+ format: z
185
+ .enum(["text", "json", "yaml", "xml"])
186
+ .optional()
187
+ .default("json")
188
+ .describe("Output format"),
189
+ hypotheticalIndexes: z
190
+ .array(z.object({
191
+ table: z.string().describe("Table name"),
192
+ columns: z.array(z.string()).describe("Columns for the index"),
193
+ indexType: z.string().optional().default("btree").describe("Index type"),
194
+ }))
195
+ .optional()
196
+ .describe("Test hypothetical indexes (requires hypopg extension)"),
197
+ }),
198
+ }, async (args) => {
199
+ const result = await explainQuery(args);
200
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
201
+ });
202
+ server.registerTool("get_top_queries", {
203
+ description: "Find slowest queries from pg_stat_statements. Requires pg_stat_statements extension enabled. Use this to identify performance bottlenecks.",
204
+ inputSchema: z.object({
205
+ limit: z
206
+ .number()
207
+ .optional()
208
+ .default(10)
209
+ .describe("Number of queries to return (1-100)"),
210
+ orderBy: z
211
+ .enum(["total_time", "mean_time", "calls"])
212
+ .optional()
213
+ .default("total_time")
214
+ .describe("Sort by total time, average time, or call count"),
215
+ minCalls: z
216
+ .number()
217
+ .optional()
218
+ .default(1)
219
+ .describe("Minimum call count to include"),
220
+ }),
221
+ }, async (args) => {
222
+ const result = await getTopQueries(args);
223
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
224
+ });
225
+ server.registerTool("analyze_workload_indexes", {
226
+ description: "Analyze database workload and recommend indexes. Uses pg_stat_statements to find slow queries and suggests indexes to improve them.",
227
+ inputSchema: z.object({
228
+ topQueriesCount: z
229
+ .number()
230
+ .optional()
231
+ .default(20)
232
+ .describe("Number of top queries to analyze (1-50)"),
233
+ includeHypothetical: z
234
+ .boolean()
235
+ .optional()
236
+ .default(false)
237
+ .describe("Test recommendations with hypothetical indexes (requires hypopg)"),
238
+ }),
239
+ }, async (args) => {
240
+ const result = await analyzeWorkloadIndexes(args);
241
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
242
+ });
243
+ server.registerTool("analyze_query_indexes", {
244
+ description: "Recommend indexes for specific SQL queries. Provide up to 10 SELECT queries and get index recommendations.",
245
+ inputSchema: z.object({
246
+ queries: z
247
+ .array(z.string())
248
+ .max(10)
249
+ .describe("SQL SELECT queries to analyze (max 10)"),
250
+ }),
251
+ }, async (args) => {
252
+ const result = await analyzeQueryIndexes(args);
253
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
254
+ });
255
+ server.registerTool("analyze_db_health", {
256
+ description: "Run comprehensive database health checks: cache hit rates, connection usage, index health (invalid/unused/duplicate), vacuum status, sequence limits, unvalidated constraints. Returns issues with severity levels.",
257
+ inputSchema: z.object({}),
258
+ }, async () => {
259
+ const result = await analyzeDbHealth();
260
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
385
261
  });
386
262
  // Graceful shutdown handling
387
263
  async function shutdown() {
388
- console.error('Shutting down PostgreSQL MCP Server...');
264
+ console.error("Shutting down PostgreSQL MCP Server...");
389
265
  try {
390
266
  resetDbManager();
267
+ await server.close();
391
268
  }
392
269
  catch (error) {
393
- console.error('Error during shutdown:', error);
270
+ console.error("Error during shutdown:", error);
394
271
  }
395
272
  process.exit(0);
396
273
  }
397
- process.on('SIGINT', shutdown);
398
- process.on('SIGTERM', shutdown);
399
- process.on('SIGHUP', shutdown);
274
+ process.on("SIGINT", shutdown);
275
+ process.on("SIGTERM", shutdown);
276
+ process.on("SIGHUP", shutdown);
400
277
  // Handle uncaught errors
401
- process.on('uncaughtException', (error) => {
402
- console.error('Uncaught exception:', error);
278
+ process.on("uncaughtException", (error) => {
279
+ console.error("Uncaught exception:", error);
403
280
  shutdown();
404
281
  });
405
- process.on('unhandledRejection', (reason, promise) => {
406
- console.error('Unhandled rejection at:', promise, 'reason:', reason);
282
+ process.on("unhandledRejection", (reason, promise) => {
283
+ console.error("Unhandled rejection at:", promise, "reason:", reason);
407
284
  });
408
285
  // Start server
409
286
  async function main() {
410
287
  const transport = new StdioServerTransport();
411
288
  await server.connect(transport);
412
- console.error('PostgreSQL MCP Server started');
289
+ console.error("PostgreSQL MCP Server started");
413
290
  }
414
291
  main().catch((error) => {
415
- console.error('Fatal error:', error);
292
+ console.error("Fatal error:", error);
416
293
  process.exit(1);
417
294
  });
418
295
  //# sourceMappingURL=index.js.map