mssql-mcp 2.0.3 → 2.3.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -63
  3. package/dist/src/config.d.ts +39 -0
  4. package/dist/src/config.js +37 -0
  5. package/dist/src/constants.d.ts +15 -0
  6. package/dist/src/constants.js +15 -0
  7. package/dist/src/db/connection.d.ts +8 -0
  8. package/dist/src/db/connection.js +80 -0
  9. package/dist/src/db/query-builders.d.ts +3 -0
  10. package/dist/src/db/query-builders.js +58 -0
  11. package/dist/src/db/validators.d.ts +5 -0
  12. package/dist/src/db/validators.js +25 -0
  13. package/dist/src/index.js +26 -0
  14. package/dist/src/resources/connection.d.ts +2 -0
  15. package/dist/src/resources/connection.js +19 -0
  16. package/dist/src/resources/metadata.d.ts +2 -0
  17. package/dist/src/resources/metadata.js +58 -0
  18. package/dist/src/schemas/outputs.d.ts +153 -0
  19. package/dist/src/schemas/outputs.js +54 -0
  20. package/dist/src/server.d.ts +2 -0
  21. package/dist/src/server.js +27 -0
  22. package/dist/src/tools/connect.d.ts +2 -0
  23. package/dist/src/tools/connect.js +45 -0
  24. package/dist/src/tools/databases.d.ts +2 -0
  25. package/dist/src/tools/databases.js +53 -0
  26. package/dist/src/tools/procedure.d.ts +2 -0
  27. package/dist/src/tools/procedure.js +106 -0
  28. package/dist/src/tools/query.d.ts +2 -0
  29. package/dist/src/tools/query.js +92 -0
  30. package/dist/src/tools/schema.d.ts +2 -0
  31. package/dist/src/tools/schema.js +96 -0
  32. package/dist/src/tools/status.d.ts +2 -0
  33. package/dist/src/tools/status.js +17 -0
  34. package/dist/src/tools/table.d.ts +2 -0
  35. package/dist/src/tools/table.js +261 -0
  36. package/dist/src/transports/http.d.ts +3 -0
  37. package/dist/src/transports/http.js +54 -0
  38. package/dist/src/transports/stdio.d.ts +2 -0
  39. package/dist/src/transports/stdio.js +23 -0
  40. package/dist/src/types.d.ts +37 -0
  41. package/dist/src/types.js +1 -0
  42. package/dist/src/utils/errors.d.ts +19 -0
  43. package/dist/src/utils/errors.js +29 -0
  44. package/dist/src/utils/format.d.ts +6 -0
  45. package/dist/src/utils/format.js +27 -0
  46. package/dist/src/utils/markdown.d.ts +3 -0
  47. package/dist/src/utils/markdown.js +33 -0
  48. package/dist/src/utils/pagination.d.ts +3 -0
  49. package/dist/src/utils/pagination.js +18 -0
  50. package/dist/tests/unit/markdown.test.d.ts +1 -0
  51. package/dist/tests/unit/markdown.test.js +70 -0
  52. package/dist/tests/unit/query-builders.test.d.ts +1 -0
  53. package/dist/tests/unit/query-builders.test.js +63 -0
  54. package/dist/tests/unit/tool-contracts.test.d.ts +1 -0
  55. package/dist/tests/unit/tool-contracts.test.js +62 -0
  56. package/dist/tests/unit/validators.test.d.ts +1 -0
  57. package/dist/tests/unit/validators.test.js +51 -0
  58. package/package.json +12 -8
  59. package/dist/index.js +0 -606
  60. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
package/dist/index.js DELETED
@@ -1,606 +0,0 @@
1
- #!/usr/bin/env node
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import sql from "mssql";
5
- import { z } from "zod";
6
- import dotenv from "dotenv";
7
- // Load environment variables
8
- dotenv.config();
9
- // Database connection configuration schema with strict validation
10
- const ConfigSchema = z.object({
11
- server: z.string().min(1, "Server address is required"),
12
- database: z.string().optional(),
13
- user: z.string().optional(),
14
- password: z.string().optional(),
15
- port: z.number().int().min(1).max(65535).optional().default(1433),
16
- trustServerCertificate: z.boolean().optional().default(true),
17
- connectionTimeout: z.number().int().min(1000).max(60000).optional().default(30000),
18
- requestTimeout: z.number().int().min(1000).max(300000).optional().default(30000),
19
- });
20
- class MSSQLMCPServer {
21
- server;
22
- pool = null;
23
- config = null;
24
- constructor() {
25
- this.server = new McpServer({
26
- name: "mssql-mcp-server",
27
- version: "2.0.3",
28
- });
29
- this.setupTools();
30
- this.setupResources();
31
- }
32
- setupTools() {
33
- // Tool: Connect to database with enhanced security validation (only uses environment variables)
34
- this.server.tool("connect_database", "Connect to MS SQL Server database with security validation (uses only environment variables for security)", {
35
- // No parameters - only environment variables will be used for security
36
- }, async (args) => {
37
- try {
38
- // SECURITY: Only use environment variables, ignore all user parameters
39
- const config = ConfigSchema.parse({
40
- server: process.env.DB_SERVER,
41
- database: process.env.DB_DATABASE,
42
- user: process.env.DB_USER,
43
- password: process.env.DB_PASSWORD,
44
- port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 1433,
45
- trustServerCertificate: process.env.DB_TRUST_SERVER_CERTIFICATE === 'true',
46
- connectionTimeout: process.env.DB_CONNECTION_TIMEOUT ? parseInt(process.env.DB_CONNECTION_TIMEOUT) : 30000,
47
- requestTimeout: process.env.DB_REQUEST_TIMEOUT ? parseInt(process.env.DB_REQUEST_TIMEOUT) : 30000,
48
- });
49
- if (!config.server) {
50
- throw new Error("Server is required. Provide it as parameter or set DB_SERVER environment variable.");
51
- }
52
- await this.connect(config);
53
- return {
54
- content: [
55
- {
56
- type: "text",
57
- text: `✅ Successfully connected to SQL Server: ${config.server}${config.database ? ` (Database: ${config.database})` : ""}`,
58
- },
59
- ],
60
- };
61
- }
62
- catch (error) {
63
- const errorMessage = error instanceof Error ? error.message : String(error);
64
- console.error("❌ Database connection failed:", errorMessage);
65
- return {
66
- content: [
67
- {
68
- type: "text",
69
- text: `❌ Failed to connect: ${errorMessage}`,
70
- },
71
- ],
72
- isError: true,
73
- };
74
- }
75
- });
76
- // Tool: Execute SQL query with enhanced security
77
- this.server.tool("execute_query", "Execute a SQL query against the connected database with security validation", {
78
- query: z.string().min(1, "Query cannot be empty").describe("SQL query to execute"),
79
- parameters: z.record(z.any()).optional().describe("Query parameters (key-value pairs) - always use parameters for user input"),
80
- }, async ({ query, parameters }) => {
81
- try {
82
- if (!this.pool) {
83
- throw new Error("No database connection. Please connect first using connect_database tool.");
84
- }
85
- const request = this.pool.request();
86
- // Add parameters if provided (recommended for security)
87
- if (parameters) {
88
- for (const [key, value] of Object.entries(parameters)) {
89
- request.input(key, value);
90
- }
91
- }
92
- const startTime = Date.now();
93
- const result = await request.query(query);
94
- const executionTime = Date.now() - startTime;
95
- return {
96
- content: [
97
- {
98
- type: "text",
99
- text: JSON.stringify({
100
- recordset: result.recordset,
101
- rowsAffected: result.rowsAffected,
102
- output: result.output,
103
- executionTime: `${executionTime}ms`,
104
- parametersUsed: parameters ? Object.keys(parameters).length : 0,
105
- }, null, 2),
106
- },
107
- ],
108
- };
109
- }
110
- catch (error) {
111
- const errorMessage = error instanceof Error ? error.message : String(error);
112
- console.error("❌ Query execution failed:", errorMessage);
113
- return {
114
- content: [
115
- {
116
- type: "text",
117
- text: `❌ Query execution failed: ${errorMessage}`,
118
- },
119
- ],
120
- isError: true,
121
- };
122
- }
123
- });
124
- // Tool: Get database schema
125
- this.server.tool("get_schema", "Get database schema information (tables, columns, etc.)", {
126
- objectType: z.enum(["tables", "views", "procedures", "functions", "all"]).optional().default("tables"),
127
- schemaName: z.string().optional().describe("Specific schema name to filter"),
128
- }, async ({ objectType, schemaName }) => {
129
- try {
130
- if (!this.pool) {
131
- throw new Error("No database connection. Please connect first.");
132
- }
133
- let query = "";
134
- if (objectType === "tables" || objectType === "all") {
135
- query += `
136
- SELECT
137
- TABLE_SCHEMA,
138
- TABLE_NAME,
139
- TABLE_TYPE,
140
- 'table' as OBJECT_TYPE
141
- FROM INFORMATION_SCHEMA.TABLES
142
- ${schemaName ? `WHERE TABLE_SCHEMA = '${schemaName}'` : ""}
143
- `;
144
- }
145
- if (objectType === "views" || objectType === "all") {
146
- if (query)
147
- query += " UNION ALL ";
148
- query += `
149
- SELECT
150
- TABLE_SCHEMA,
151
- TABLE_NAME,
152
- 'VIEW' as TABLE_TYPE,
153
- 'view' as OBJECT_TYPE
154
- FROM INFORMATION_SCHEMA.VIEWS
155
- ${schemaName ? `WHERE TABLE_SCHEMA = '${schemaName}'` : ""}
156
- `;
157
- }
158
- if (objectType === "procedures" || objectType === "all") {
159
- if (query)
160
- query += " UNION ALL ";
161
- query += `
162
- SELECT
163
- ROUTINE_SCHEMA as TABLE_SCHEMA,
164
- ROUTINE_NAME as TABLE_NAME,
165
- 'PROCEDURE' as TABLE_TYPE,
166
- 'procedure' as OBJECT_TYPE
167
- FROM INFORMATION_SCHEMA.ROUTINES
168
- WHERE ROUTINE_TYPE = 'PROCEDURE'
169
- ${schemaName ? `AND ROUTINE_SCHEMA = '${schemaName}'` : ""}
170
- `;
171
- }
172
- if (objectType === "functions" || objectType === "all") {
173
- if (query)
174
- query += " UNION ALL ";
175
- query += `
176
- SELECT
177
- ROUTINE_SCHEMA as TABLE_SCHEMA,
178
- ROUTINE_NAME as TABLE_NAME,
179
- 'FUNCTION' as TABLE_TYPE,
180
- 'function' as OBJECT_TYPE
181
- FROM INFORMATION_SCHEMA.ROUTINES
182
- WHERE ROUTINE_TYPE = 'FUNCTION'
183
- ${schemaName ? `AND ROUTINE_SCHEMA = '${schemaName}'` : ""}
184
- `;
185
- }
186
- query += " ORDER BY TABLE_SCHEMA, TABLE_NAME";
187
- const result = await this.pool.request().query(query);
188
- return {
189
- content: [
190
- {
191
- type: "text",
192
- text: JSON.stringify(result.recordset, null, 2),
193
- },
194
- ],
195
- };
196
- }
197
- catch (error) {
198
- return {
199
- content: [
200
- {
201
- type: "text",
202
- text: `Schema query failed: ${error instanceof Error ? error.message : String(error)}`,
203
- },
204
- ],
205
- isError: true,
206
- };
207
- }
208
- });
209
- // Tool: Get table structure
210
- this.server.tool("describe_table", "Get detailed structure of a specific table", {
211
- tableName: z.string().describe("Name of the table"),
212
- schemaName: z.string().optional().default("dbo").describe("Schema name"),
213
- }, async ({ tableName, schemaName }) => {
214
- try {
215
- if (!this.pool) {
216
- throw new Error("No database connection. Please connect first.");
217
- }
218
- const query = `
219
- SELECT
220
- COLUMN_NAME,
221
- DATA_TYPE,
222
- CHARACTER_MAXIMUM_LENGTH,
223
- NUMERIC_PRECISION,
224
- NUMERIC_SCALE,
225
- IS_NULLABLE,
226
- COLUMN_DEFAULT,
227
- ORDINAL_POSITION
228
- FROM INFORMATION_SCHEMA.COLUMNS
229
- WHERE TABLE_NAME = @tableName
230
- AND TABLE_SCHEMA = @schemaName
231
- ORDER BY ORDINAL_POSITION
232
- `;
233
- const result = await this.pool.request()
234
- .input('tableName', sql.VarChar, tableName)
235
- .input('schemaName', sql.VarChar, schemaName)
236
- .query(query);
237
- return {
238
- content: [
239
- {
240
- type: "text",
241
- text: JSON.stringify(result.recordset, null, 2),
242
- },
243
- ],
244
- };
245
- }
246
- catch (error) {
247
- return {
248
- content: [
249
- {
250
- type: "text",
251
- text: `Table description failed: ${error instanceof Error ? error.message : String(error)}`,
252
- },
253
- ],
254
- isError: true,
255
- };
256
- }
257
- });
258
- // Tool: Get enhanced connection status
259
- this.server.tool("connection_status", "Check current database connection status with detailed information", {}, async () => {
260
- const isConnected = this.pool?.connected || false;
261
- const status = {
262
- connected: isConnected,
263
- server: this.config?.server || "Not configured",
264
- database: this.config?.database || "Not specified",
265
- port: this.config?.port || "Not specified",
266
- connectionTime: isConnected ? new Date().toISOString() : null,
267
- securityFeatures: {
268
- sqlInjectionProtection: "Enabled",
269
- },
270
- poolInfo: this.pool ? {
271
- size: this.pool.size,
272
- available: this.pool.available,
273
- pending: this.pool.pending,
274
- borrowed: this.pool.borrowed,
275
- } : null,
276
- };
277
- return {
278
- content: [
279
- {
280
- type: "text",
281
- text: JSON.stringify(status, null, 2),
282
- },
283
- ],
284
- };
285
- });
286
- // Tool: Disconnect from database
287
- this.server.tool("disconnect_database", "Disconnect from the current database", {}, async () => {
288
- try {
289
- if (this.pool) {
290
- await this.pool.close();
291
- this.pool = null;
292
- this.config = null;
293
- }
294
- return {
295
- content: [
296
- {
297
- type: "text",
298
- text: "Successfully disconnected from database",
299
- },
300
- ],
301
- };
302
- }
303
- catch (error) {
304
- return {
305
- content: [
306
- {
307
- type: "text",
308
- text: `Disconnect failed: ${error instanceof Error ? error.message : String(error)}`,
309
- },
310
- ],
311
- isError: true,
312
- };
313
- }
314
- });
315
- // Tool: Get table data with enhanced security and validation
316
- this.server.tool("get_table_data", "Get data from a specific table with optional filtering, pagination and input validation", {
317
- tableName: z.string().min(1).regex(/^[a-zA-Z0-9_]+$/, "Table name can only contain letters, numbers, and underscores").describe("Name of the table"),
318
- schemaName: z.string().regex(/^[a-zA-Z0-9_]+$/, "Schema name can only contain letters, numbers, and underscores").optional().default("dbo").describe("Schema name"),
319
- limit: z.number().int().min(1).max(10000).optional().default(100).describe("Maximum number of rows to return (1-10000)"),
320
- offset: z.number().int().min(0).optional().default(0).describe("Number of rows to skip"),
321
- whereClause: z.string().optional().describe("WHERE clause (without the WHERE keyword) - use parameters for values"),
322
- orderBy: z.string().optional().describe("ORDER BY clause (without the ORDER BY keyword)"),
323
- parameters: z.record(z.any()).optional().describe("Parameters for WHERE clause"),
324
- }, async ({ tableName, schemaName, limit, offset, whereClause, orderBy, parameters }) => {
325
- try {
326
- if (!this.pool) {
327
- throw new Error("No database connection. Please connect first.");
328
- }
329
- // Security: Validate table and schema names to prevent SQL injection
330
- const tableNamePattern = /^[a-zA-Z0-9_]+$/;
331
- if (!tableNamePattern.test(tableName)) {
332
- throw new Error("Invalid table name. Only letters, numbers, and underscores are allowed.");
333
- }
334
- if (!tableNamePattern.test(schemaName)) {
335
- throw new Error("Invalid schema name. Only letters, numbers, and underscores are allowed.");
336
- }
337
- // Build query using parameterized approach
338
- let query = `SELECT * FROM [${schemaName}].[${tableName}]`;
339
- const request = this.pool.request();
340
- if (whereClause) {
341
- // Add parameters for WHERE clause if provided
342
- if (parameters) {
343
- for (const [key, value] of Object.entries(parameters)) {
344
- request.input(key, value);
345
- }
346
- }
347
- query += ` WHERE ${whereClause}`;
348
- }
349
- if (orderBy) {
350
- // Validate ORDER BY clause for basic security
351
- // Allow dotted identifiers, bracketed identifiers, commas, spaces and optional ASC/DESC per column
352
- const orderByPattern = /^([\[\]a-zA-Z0-9_.]+(\s+(ASC|DESC))?)(\s*,\s*[\[\]a-zA-Z0-9_.]+(\s+(ASC|DESC))?)*$/i;
353
- if (!orderByPattern.test(orderBy)) {
354
- throw new Error("Invalid ORDER BY clause. Only column names, commas, spaces, ASC, and DESC are allowed.");
355
- }
356
- query += ` ORDER BY ${orderBy}`;
357
- }
358
- else {
359
- // Default ordering for pagination
360
- query += ` ORDER BY (SELECT NULL)`;
361
- }
362
- query += ` OFFSET ${offset} ROWS FETCH NEXT ${limit} ROWS ONLY`;
363
- const startTime = Date.now();
364
- const result = await request.query(query);
365
- const executionTime = Date.now() - startTime;
366
- return {
367
- content: [
368
- {
369
- type: "text",
370
- text: JSON.stringify({
371
- data: result.recordset,
372
- metadata: {
373
- rowCount: result.recordset.length,
374
- offset: offset,
375
- limit: limit,
376
- executionTime: `${executionTime}ms`,
377
- table: `${schemaName}.${tableName}`,
378
- hasWhereClause: !!whereClause,
379
- parametersUsed: parameters ? Object.keys(parameters).length : 0,
380
- }
381
- }, null, 2),
382
- },
383
- ],
384
- };
385
- }
386
- catch (error) {
387
- const errorMessage = error instanceof Error ? error.message : String(error);
388
- console.error("❌ Get table data failed:", errorMessage);
389
- return {
390
- content: [
391
- {
392
- type: "text",
393
- text: `❌ Get table data failed: ${errorMessage}`,
394
- },
395
- ],
396
- isError: true,
397
- };
398
- }
399
- });
400
- // Tool: Execute stored procedure
401
- this.server.tool("execute_procedure", "Execute a stored procedure with parameters", {
402
- procedureName: z.string().describe("Name of the stored procedure"),
403
- schemaName: z.string().optional().default("dbo").describe("Schema name"),
404
- parameters: z.record(z.any()).optional().describe("Procedure parameters (key-value pairs)"),
405
- }, async ({ procedureName, schemaName, parameters }) => {
406
- try {
407
- if (!this.pool) {
408
- throw new Error("No database connection. Please connect first.");
409
- }
410
- const request = this.pool.request();
411
- // Add parameters if provided
412
- if (parameters) {
413
- for (const [key, value] of Object.entries(parameters)) {
414
- request.input(key, value);
415
- }
416
- }
417
- const result = await request.execute(`[${schemaName}].[${procedureName}]`);
418
- return {
419
- content: [
420
- {
421
- type: "text",
422
- text: JSON.stringify({
423
- recordsets: result.recordsets,
424
- rowsAffected: result.rowsAffected,
425
- output: result.output,
426
- returnValue: result.returnValue,
427
- }, null, 2),
428
- },
429
- ],
430
- };
431
- }
432
- catch (error) {
433
- return {
434
- content: [
435
- {
436
- type: "text",
437
- text: `Procedure execution failed: ${error instanceof Error ? error.message : String(error)}`,
438
- },
439
- ],
440
- isError: true,
441
- };
442
- }
443
- });
444
- // Tool: Get database list
445
- this.server.tool("list_databases", "List all databases on the connected SQL Server instance", {}, async () => {
446
- try {
447
- if (!this.pool) {
448
- throw new Error("No database connection. Please connect first.");
449
- }
450
- const query = `
451
- SELECT
452
- name,
453
- database_id,
454
- create_date,
455
- collation_name,
456
- state_desc,
457
- user_access_desc,
458
- is_read_only,
459
- is_auto_close_on,
460
- is_auto_shrink_on,
461
- recovery_model_desc
462
- FROM sys.databases
463
- ORDER BY name
464
- `;
465
- const result = await this.pool.request().query(query);
466
- return {
467
- content: [
468
- {
469
- type: "text",
470
- text: JSON.stringify(result.recordset, null, 2),
471
- },
472
- ],
473
- };
474
- }
475
- catch (error) {
476
- return {
477
- content: [
478
- {
479
- type: "text",
480
- text: `List databases failed: ${error instanceof Error ? error.message : String(error)}`,
481
- },
482
- ],
483
- isError: true,
484
- };
485
- }
486
- });
487
- }
488
- setupResources() {
489
- // Resource: Current connection info
490
- this.server.resource("connection-info", "mssql://connection/info", async () => {
491
- const info = {
492
- connected: this.pool?.connected || false,
493
- config: this.config ? {
494
- server: this.config.server,
495
- database: this.config.database,
496
- port: this.config.port,
497
- } : null,
498
- };
499
- return {
500
- contents: [
501
- {
502
- uri: "mssql://connection/info",
503
- text: JSON.stringify(info, null, 2),
504
- mimeType: "application/json",
505
- },
506
- ],
507
- };
508
- });
509
- }
510
- async connect(config) {
511
- try {
512
- // Close existing connection if any
513
- if (this.pool) {
514
- console.error("Closing existing connection...");
515
- await this.pool.close();
516
- }
517
- console.error(`Connecting to ${config.server}:${config.port}`);
518
- // Create new connection pool with enhanced security settings
519
- this.pool = new sql.ConnectionPool({
520
- server: config.server,
521
- database: config.database,
522
- user: config.user,
523
- password: config.password,
524
- port: config.port,
525
- options: {
526
- trustServerCertificate: config.trustServerCertificate,
527
- enableArithAbort: true,
528
- encrypt: !config.trustServerCertificate, // Enable encryption when not trusting server certificate
529
- },
530
- connectionTimeout: config.connectionTimeout,
531
- requestTimeout: config.requestTimeout,
532
- // Connection pool settings for better resource management
533
- pool: {
534
- max: 10,
535
- min: 0,
536
- idleTimeoutMillis: 30000,
537
- },
538
- });
539
- // Set up event handlers for better monitoring
540
- this.pool.on('connect', () => {
541
- console.error('Database connected');
542
- });
543
- this.pool.on('error', (err) => {
544
- console.error('Database error:', err);
545
- });
546
- await this.pool.connect();
547
- this.config = config;
548
- console.error(`Connected to ${config.server}${config.database ? `/${config.database}` : ''}`);
549
- }
550
- catch (error) {
551
- console.error("Connection failed:", error);
552
- if (this.pool) {
553
- try {
554
- await this.pool.close();
555
- }
556
- catch (closeError) {
557
- console.error("Error closing failed connection:", closeError);
558
- }
559
- this.pool = null;
560
- }
561
- this.config = null;
562
- throw error;
563
- }
564
- }
565
- async run() {
566
- const transport = new StdioServerTransport();
567
- // Enhanced graceful shutdown handling
568
- const shutdown = async (signal) => {
569
- console.error(`\nShutting down (${signal})...`);
570
- try {
571
- if (this.pool) {
572
- console.error("Closing database connection...");
573
- await this.pool.close();
574
- console.error("Database connection closed");
575
- }
576
- }
577
- catch (error) {
578
- console.error("Shutdown error:", error);
579
- }
580
- console.error("Server stopped");
581
- process.exit(0);
582
- };
583
- // Handle various shutdown signals
584
- process.on('SIGINT', () => shutdown('SIGINT'));
585
- process.on('SIGTERM', () => shutdown('SIGTERM'));
586
- process.on('SIGUSR2', () => shutdown('SIGUSR2')); // For nodemon
587
- // Handle uncaught exceptions
588
- process.on('uncaughtException', (error) => {
589
- console.error('Uncaught Exception:', error);
590
- shutdown('uncaughtException');
591
- });
592
- process.on('unhandledRejection', (reason, promise) => {
593
- console.error('Unhandled Rejection:', reason);
594
- shutdown('unhandledRejection');
595
- });
596
- console.error("MSSQL MCP Server v2.0.3 starting...");
597
- await this.server.connect(transport);
598
- console.error("Server ready");
599
- }
600
- }
601
- // Start the server
602
- const server = new MSSQLMCPServer();
603
- server.run().catch((error) => {
604
- console.error("Server failed to start:", error);
605
- process.exit(1);
606
- });
File without changes