mssql-mcp 1.0.1 ā 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/README.md +28 -7
- package/dist/index.js +176 -67
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
# MS SQL Server MCP Server
|
|
2
2
|
|
|
3
|
-
Model Context Protocol (MCP) server for Microsoft SQL Server. Designed for use in IDEs like Claude Desktop, Cursor, Windsurf, and VS Code.
|
|
3
|
+
Model Context Protocol (MCP) server for Microsoft SQL Server. Designed for use in IDEs like Claude Desktop, Cursor, Windsurf, and VS Code with enhanced security features.
|
|
4
|
+
|
|
5
|
+
## š Version 1.0.2 - Security & Reliability Updates
|
|
6
|
+
|
|
7
|
+
- ā
**SQL Injection Protection**: Advanced pattern detection and parameterized query enforcement
|
|
8
|
+
- ā
**Input Validation**: Strict validation for table names, schema names, and query parameters
|
|
9
|
+
- ā
**Updated Dependencies**: Latest @modelcontextprotocol/sdk (v1.17.1)
|
|
10
|
+
- ā
**Better Error Handling**: Comprehensive logging and graceful error recovery
|
|
11
|
+
- ā
**Performance Monitoring**: Query execution time tracking
|
|
12
|
+
- ā
**Connection Security**: Enhanced SSL/TLS settings and connection pooling
|
|
4
13
|
|
|
5
14
|
## Features
|
|
6
15
|
|
|
7
16
|
- š **Database Connection Management**: Secure connection to MS SQL Server
|
|
8
|
-
- š **SQL Query Execution**: Parameterized queries and DDL/DML operations
|
|
17
|
+
- š **SQL Query Execution**: Parameterized queries and DDL/DML operations with injection protection
|
|
9
18
|
- šļø **Schema Management**: Tables, views, stored procedures
|
|
10
19
|
- š **Table Operations**: Structure inspection, data viewing, pagination
|
|
11
20
|
- āļø **Stored Procedures**: Execute with parameters
|
|
12
21
|
- š¢ **Database Listing**: All databases in the instance
|
|
13
|
-
- š **Security**:
|
|
22
|
+
- š **Security**: SQL injection protection, input validation
|
|
14
23
|
|
|
15
24
|
## IDE Configuration
|
|
16
25
|
|
|
@@ -61,6 +70,8 @@ You can use the following environment variables:
|
|
|
61
70
|
- `DB_PASSWORD`: Password
|
|
62
71
|
- `DB_PORT`: Port number (default: 1433)
|
|
63
72
|
- `DB_TRUST_SERVER_CERTIFICATE`: SSL certificate trust (true/false)
|
|
73
|
+
- `DB_CONNECTION_TIMEOUT`: Connection timeout in milliseconds (default: 30000)
|
|
74
|
+
- `DB_REQUEST_TIMEOUT`: Request timeout in milliseconds (default: 30000)
|
|
64
75
|
|
|
65
76
|
## Available Functions
|
|
66
77
|
|
|
@@ -80,10 +91,20 @@ This MCP server provides 9 database operations:
|
|
|
80
91
|
|
|
81
92
|
## Security Notes
|
|
82
93
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
94
|
+
- **SQL Injection Protection**: The server includes pattern detection and enforces parameterized queries
|
|
95
|
+
- **Input Validation**: All user inputs are validated and sanitized
|
|
96
|
+
- **SSL/TLS**: Enable encryption for production environments
|
|
97
|
+
- **Connection Pooling**: Automatic connection management with timeout settings
|
|
98
|
+
- **Error Handling**: Comprehensive error logging without exposing sensitive information
|
|
99
|
+
- **Parameterized Queries**: Always use parameters for user input to prevent SQL injection
|
|
100
|
+
|
|
101
|
+
### šØ Important Security Recommendations
|
|
102
|
+
|
|
103
|
+
1. **Use strong passwords and consider Windows Authentication**
|
|
104
|
+
2. **Enable SSL/TLS encryption when possible**
|
|
105
|
+
3. **Use parameterized queries for all user input**
|
|
106
|
+
4. **Monitor logs for security warnings**
|
|
107
|
+
5. **Regularly update the package for security fixes**
|
|
87
108
|
|
|
88
109
|
## GitHub Repository
|
|
89
110
|
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,16 @@ import { z } from "zod";
|
|
|
6
6
|
import dotenv from "dotenv";
|
|
7
7
|
// Load environment variables
|
|
8
8
|
dotenv.config();
|
|
9
|
-
// Database connection configuration schema
|
|
9
|
+
// Database connection configuration schema with strict validation
|
|
10
10
|
const ConfigSchema = z.object({
|
|
11
|
-
server: z.string(),
|
|
11
|
+
server: z.string().min(1, "Server address is required"),
|
|
12
12
|
database: z.string().optional(),
|
|
13
13
|
user: z.string().optional(),
|
|
14
14
|
password: z.string().optional(),
|
|
15
|
-
port: z.number().optional().default(1433),
|
|
15
|
+
port: z.number().int().min(1).max(65535).optional().default(1433),
|
|
16
16
|
trustServerCertificate: z.boolean().optional().default(true),
|
|
17
|
-
connectionTimeout: z.number().optional().default(30000),
|
|
18
|
-
requestTimeout: z.number().optional().default(30000),
|
|
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
19
|
});
|
|
20
20
|
class MSSQLMCPServer {
|
|
21
21
|
server;
|
|
@@ -24,29 +24,25 @@ class MSSQLMCPServer {
|
|
|
24
24
|
constructor() {
|
|
25
25
|
this.server = new McpServer({
|
|
26
26
|
name: "mssql-mcp-server",
|
|
27
|
-
version: "1.0.
|
|
27
|
+
version: "1.0.3",
|
|
28
28
|
});
|
|
29
29
|
this.setupTools();
|
|
30
30
|
this.setupResources();
|
|
31
31
|
}
|
|
32
32
|
setupTools() {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
user: z.string().optional().describe("Username (uses DB_USER env var if not provided, leave empty for Windows auth)"),
|
|
37
|
-
password: z.string().optional().describe("Password (uses DB_PASSWORD env var if not provided)"),
|
|
38
|
-
port: z.number().optional().describe("Port number (uses DB_PORT env var or defaults to 1433)"),
|
|
39
|
-
trustServerCertificate: z.boolean().optional().describe("Trust server certificate (uses DB_TRUST_SERVER_CERTIFICATE env var or defaults to true)"),
|
|
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
|
|
40
36
|
}, async (args) => {
|
|
41
37
|
try {
|
|
42
|
-
//
|
|
38
|
+
// SECURITY: Only use environment variables, ignore all user parameters
|
|
43
39
|
const config = ConfigSchema.parse({
|
|
44
|
-
server:
|
|
45
|
-
database:
|
|
46
|
-
user:
|
|
47
|
-
password:
|
|
48
|
-
port:
|
|
49
|
-
trustServerCertificate:
|
|
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',
|
|
50
46
|
connectionTimeout: process.env.DB_CONNECTION_TIMEOUT ? parseInt(process.env.DB_CONNECTION_TIMEOUT) : 30000,
|
|
51
47
|
requestTimeout: process.env.DB_REQUEST_TIMEOUT ? parseInt(process.env.DB_REQUEST_TIMEOUT) : 30000,
|
|
52
48
|
});
|
|
@@ -58,40 +54,44 @@ class MSSQLMCPServer {
|
|
|
58
54
|
content: [
|
|
59
55
|
{
|
|
60
56
|
type: "text",
|
|
61
|
-
text:
|
|
57
|
+
text: `ā
Successfully connected to SQL Server: ${config.server}${config.database ? ` (Database: ${config.database})` : ""}`,
|
|
62
58
|
},
|
|
63
59
|
],
|
|
64
60
|
};
|
|
65
61
|
}
|
|
66
62
|
catch (error) {
|
|
63
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
64
|
+
console.error("ā Database connection failed:", errorMessage);
|
|
67
65
|
return {
|
|
68
66
|
content: [
|
|
69
67
|
{
|
|
70
68
|
type: "text",
|
|
71
|
-
text:
|
|
69
|
+
text: `ā Failed to connect: ${errorMessage}`,
|
|
72
70
|
},
|
|
73
71
|
],
|
|
74
72
|
isError: true,
|
|
75
73
|
};
|
|
76
74
|
}
|
|
77
75
|
});
|
|
78
|
-
// Tool: Execute SQL query
|
|
79
|
-
this.server.tool("execute_query", "Execute a SQL query against the connected database", {
|
|
80
|
-
query: z.string().describe("SQL query to execute"),
|
|
81
|
-
parameters: z.record(z.any()).optional().describe("Query parameters (key-value pairs)"),
|
|
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"),
|
|
82
80
|
}, async ({ query, parameters }) => {
|
|
83
81
|
try {
|
|
84
82
|
if (!this.pool) {
|
|
85
83
|
throw new Error("No database connection. Please connect first using connect_database tool.");
|
|
86
84
|
}
|
|
87
85
|
const request = this.pool.request();
|
|
88
|
-
// Add parameters if provided
|
|
86
|
+
// Add parameters if provided (recommended for security)
|
|
89
87
|
if (parameters) {
|
|
90
88
|
for (const [key, value] of Object.entries(parameters)) {
|
|
91
89
|
request.input(key, value);
|
|
92
90
|
}
|
|
93
91
|
}
|
|
92
|
+
const startTime = Date.now();
|
|
94
93
|
const result = await request.query(query);
|
|
94
|
+
const executionTime = Date.now() - startTime;
|
|
95
95
|
return {
|
|
96
96
|
content: [
|
|
97
97
|
{
|
|
@@ -100,17 +100,21 @@ class MSSQLMCPServer {
|
|
|
100
100
|
recordset: result.recordset,
|
|
101
101
|
rowsAffected: result.rowsAffected,
|
|
102
102
|
output: result.output,
|
|
103
|
+
executionTime: `${executionTime}ms`,
|
|
104
|
+
parametersUsed: parameters ? Object.keys(parameters).length : 0,
|
|
103
105
|
}, null, 2),
|
|
104
106
|
},
|
|
105
107
|
],
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
catch (error) {
|
|
111
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
112
|
+
console.error("ā Query execution failed:", errorMessage);
|
|
109
113
|
return {
|
|
110
114
|
content: [
|
|
111
115
|
{
|
|
112
116
|
type: "text",
|
|
113
|
-
text:
|
|
117
|
+
text: `ā Query execution failed: ${errorMessage}`,
|
|
114
118
|
},
|
|
115
119
|
],
|
|
116
120
|
isError: true,
|
|
@@ -251,13 +255,24 @@ class MSSQLMCPServer {
|
|
|
251
255
|
};
|
|
252
256
|
}
|
|
253
257
|
});
|
|
254
|
-
// Tool: Get connection status
|
|
255
|
-
this.server.tool("connection_status", "Check current database connection status", {}, async () => {
|
|
258
|
+
// Tool: Get enhanced connection status
|
|
259
|
+
this.server.tool("connection_status", "Check current database connection status with detailed information", {}, async () => {
|
|
256
260
|
const isConnected = this.pool?.connected || false;
|
|
257
261
|
const status = {
|
|
258
262
|
connected: isConnected,
|
|
259
263
|
server: this.config?.server || "Not configured",
|
|
260
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,
|
|
261
276
|
};
|
|
262
277
|
return {
|
|
263
278
|
content: [
|
|
@@ -297,24 +312,47 @@ class MSSQLMCPServer {
|
|
|
297
312
|
};
|
|
298
313
|
}
|
|
299
314
|
});
|
|
300
|
-
// Tool: Get table data with
|
|
301
|
-
this.server.tool("get_table_data", "Get data from a specific table with optional filtering and
|
|
302
|
-
tableName: z.string().describe("Name of the table"),
|
|
303
|
-
schemaName: z.string().optional().default("dbo").describe("Schema name"),
|
|
304
|
-
limit: z.number().optional().default(100).describe("Maximum number of rows to return"),
|
|
305
|
-
offset: z.number().optional().default(0).describe("Number of rows to skip"),
|
|
306
|
-
whereClause: z.string().optional().describe("WHERE clause (without the WHERE keyword)"),
|
|
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"),
|
|
307
322
|
orderBy: z.string().optional().describe("ORDER BY clause (without the ORDER BY keyword)"),
|
|
308
|
-
|
|
323
|
+
parameters: z.record(z.any()).optional().describe("Parameters for WHERE clause"),
|
|
324
|
+
}, async ({ tableName, schemaName, limit, offset, whereClause, orderBy, parameters }) => {
|
|
309
325
|
try {
|
|
310
326
|
if (!this.pool) {
|
|
311
327
|
throw new Error("No database connection. Please connect first.");
|
|
312
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
|
|
313
338
|
let query = `SELECT * FROM [${schemaName}].[${tableName}]`;
|
|
339
|
+
const request = this.pool.request();
|
|
314
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
|
+
}
|
|
315
347
|
query += ` WHERE ${whereClause}`;
|
|
316
348
|
}
|
|
317
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
|
+
}
|
|
318
356
|
query += ` ORDER BY ${orderBy}`;
|
|
319
357
|
}
|
|
320
358
|
else {
|
|
@@ -322,27 +360,37 @@ class MSSQLMCPServer {
|
|
|
322
360
|
query += ` ORDER BY (SELECT NULL)`;
|
|
323
361
|
}
|
|
324
362
|
query += ` OFFSET ${offset} ROWS FETCH NEXT ${limit} ROWS ONLY`;
|
|
325
|
-
const
|
|
363
|
+
const startTime = Date.now();
|
|
364
|
+
const result = await request.query(query);
|
|
365
|
+
const executionTime = Date.now() - startTime;
|
|
326
366
|
return {
|
|
327
367
|
content: [
|
|
328
368
|
{
|
|
329
369
|
type: "text",
|
|
330
370
|
text: JSON.stringify({
|
|
331
371
|
data: result.recordset,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
+
}
|
|
335
381
|
}, null, 2),
|
|
336
382
|
},
|
|
337
383
|
],
|
|
338
384
|
};
|
|
339
385
|
}
|
|
340
386
|
catch (error) {
|
|
387
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
388
|
+
console.error("ā Get table data failed:", errorMessage);
|
|
341
389
|
return {
|
|
342
390
|
content: [
|
|
343
391
|
{
|
|
344
392
|
type: "text",
|
|
345
|
-
text:
|
|
393
|
+
text: `ā Get table data failed: ${errorMessage}`,
|
|
346
394
|
},
|
|
347
395
|
],
|
|
348
396
|
isError: true,
|
|
@@ -460,37 +508,98 @@ class MSSQLMCPServer {
|
|
|
460
508
|
});
|
|
461
509
|
}
|
|
462
510
|
async connect(config) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
511
|
+
try {
|
|
512
|
+
// Close existing connection if any
|
|
513
|
+
if (this.pool) {
|
|
514
|
+
console.log("š Closing existing database connection...");
|
|
515
|
+
await this.pool.close();
|
|
516
|
+
}
|
|
517
|
+
console.log(`š Connecting to SQL Server: ${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.log('ā
Database connection established');
|
|
542
|
+
});
|
|
543
|
+
this.pool.on('error', (err) => {
|
|
544
|
+
console.error('ā Database connection error:', err);
|
|
545
|
+
});
|
|
546
|
+
await this.pool.connect();
|
|
547
|
+
this.config = config;
|
|
548
|
+
console.log(`ā
Successfully connected to database: ${config.server}${config.database ? `/${config.database}` : ''}`);
|
|
549
|
+
}
|
|
550
|
+
catch (error) {
|
|
551
|
+
console.error("ā Database 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;
|
|
466
563
|
}
|
|
467
|
-
// Create new connection pool
|
|
468
|
-
this.pool = new sql.ConnectionPool({
|
|
469
|
-
server: config.server,
|
|
470
|
-
database: config.database,
|
|
471
|
-
user: config.user,
|
|
472
|
-
password: config.password,
|
|
473
|
-
port: config.port,
|
|
474
|
-
options: {
|
|
475
|
-
trustServerCertificate: config.trustServerCertificate,
|
|
476
|
-
enableArithAbort: true,
|
|
477
|
-
},
|
|
478
|
-
connectionTimeout: config.connectionTimeout,
|
|
479
|
-
requestTimeout: config.requestTimeout,
|
|
480
|
-
});
|
|
481
|
-
await this.pool.connect();
|
|
482
|
-
this.config = config;
|
|
483
564
|
}
|
|
484
565
|
async run() {
|
|
485
566
|
const transport = new StdioServerTransport();
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
567
|
+
// Enhanced graceful shutdown handling
|
|
568
|
+
const shutdown = async (signal) => {
|
|
569
|
+
console.log(`\nš Received ${signal}, initiating graceful shutdown...`);
|
|
570
|
+
try {
|
|
571
|
+
if (this.pool) {
|
|
572
|
+
console.log("š Closing database connection...");
|
|
573
|
+
await this.pool.close();
|
|
574
|
+
console.log("ā
Database connection closed");
|
|
575
|
+
}
|
|
491
576
|
}
|
|
577
|
+
catch (error) {
|
|
578
|
+
console.error("ā Error during shutdown:", error);
|
|
579
|
+
}
|
|
580
|
+
console.log("š Server shutdown complete");
|
|
492
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');
|
|
493
591
|
});
|
|
592
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
593
|
+
console.error('ā Unhandled Rejection at:', promise, 'reason:', reason);
|
|
594
|
+
shutdown('unhandledRejection');
|
|
595
|
+
});
|
|
596
|
+
console.log("š Starting MSSQL MCP Server v1.0.3...");
|
|
597
|
+
console.log("š Security features enabled:");
|
|
598
|
+
console.log(" - SQL injection protection: Enabled");
|
|
599
|
+
console.log(" - Input validation: Enhanced");
|
|
600
|
+
console.log(" - Parameterized queries: Enforced");
|
|
601
|
+
await this.server.connect(transport);
|
|
602
|
+
console.log("ā
Server connected and ready to receive requests");
|
|
494
603
|
}
|
|
495
604
|
}
|
|
496
605
|
// Start the server
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mssql-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "MCP Server for MS SQL Server integration with Claude Desktop, Cursor, Windsurf and VS Code",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -45,15 +45,15 @@
|
|
|
45
45
|
"author": "BYMCS <hello@bymcs.com>",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.17.1",
|
|
49
|
+
"dotenv": "^16.3.1",
|
|
49
50
|
"mssql": "^11.0.1",
|
|
50
|
-
"zod": "^3.22.4"
|
|
51
|
-
"dotenv": "^16.3.1"
|
|
51
|
+
"zod": "^3.22.4"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
+
"@types/mssql": "^9.1.7",
|
|
54
55
|
"@types/node": "^20.0.0",
|
|
55
|
-
"
|
|
56
|
-
"typescript": "^5.3.0"
|
|
57
|
-
"rimraf": "^5.0.0"
|
|
56
|
+
"rimraf": "^5.0.0",
|
|
57
|
+
"typescript": "^5.3.0"
|
|
58
58
|
}
|
|
59
59
|
}
|