@eamonboyle/mssql-mcp 1.6.0 → 2.0.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/README.md +62 -12
- package/dist/apps/queryResultsApp.d.ts +18 -0
- package/dist/apps/queryResultsApp.d.ts.map +1 -0
- package/dist/apps/queryResultsApp.js +272 -0
- package/dist/apps/queryResultsApp.js.map +1 -0
- package/dist/checkNodeVersion.d.ts +2 -0
- package/dist/checkNodeVersion.d.ts.map +1 -0
- package/dist/checkNodeVersion.js +9 -0
- package/dist/checkNodeVersion.js.map +1 -0
- package/dist/config.d.ts +30 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +66 -5
- package/dist/config.js.map +1 -1
- package/dist/confirmationMessage.d.ts +2 -0
- package/dist/confirmationMessage.d.ts.map +1 -0
- package/dist/confirmationMessage.js +105 -0
- package/dist/confirmationMessage.js.map +1 -0
- package/dist/db.d.ts +20 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +118 -16
- package/dist/db.js.map +1 -1
- package/dist/filteredRead.js +0 -0
- package/dist/httpServer.d.ts +25 -0
- package/dist/httpServer.d.ts.map +1 -0
- package/dist/httpServer.js +128 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -395
- package/dist/index.js.map +1 -1
- package/dist/mcpResults.d.ts +1 -1
- package/dist/mcpResults.d.ts.map +1 -1
- package/dist/mcpResults.js +2 -2
- package/dist/mcpResults.js.map +1 -1
- package/dist/nodeVersion.d.ts +14 -0
- package/dist/nodeVersion.d.ts.map +1 -0
- package/dist/nodeVersion.js +23 -0
- package/dist/nodeVersion.js.map +1 -0
- package/dist/packageInfo.d.ts +3 -0
- package/dist/packageInfo.d.ts.map +1 -0
- package/dist/packageInfo.js +5 -0
- package/dist/packageInfo.js.map +1 -0
- package/dist/promptRegistry.d.ts +1 -1
- package/dist/promptRegistry.d.ts.map +1 -1
- package/dist/promptRegistry.js +1 -1
- package/dist/promptRegistry.js.map +1 -1
- package/dist/resourceRegistry.d.ts +3 -1
- package/dist/resourceRegistry.d.ts.map +1 -1
- package/dist/resourceRegistry.js +3 -2
- package/dist/resourceRegistry.js.map +1 -1
- package/dist/schema.js +0 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +320 -0
- package/dist/server.js.map +1 -0
- package/dist/serverState.js +2 -4
- package/dist/serverState.js.map +1 -1
- package/dist/sql.js +0 -0
- package/dist/sqlErrors.d.ts +10 -0
- package/dist/sqlErrors.d.ts.map +1 -0
- package/dist/sqlErrors.js +32 -0
- package/dist/sqlErrors.js.map +1 -0
- package/dist/toolRegistry.d.ts +1 -1
- package/dist/toolRegistry.d.ts.map +1 -1
- package/dist/toolRegistry.js +1 -1
- package/dist/toolRegistry.js.map +1 -1
- package/dist/tools/AnalyzeTableTool.js +2 -4
- package/dist/tools/AnalyzeTableTool.js.map +1 -1
- package/dist/tools/CreateIndexTool.js +2 -4
- package/dist/tools/CreateIndexTool.js.map +1 -1
- package/dist/tools/CreateTableTool.js +2 -4
- package/dist/tools/CreateTableTool.js.map +1 -1
- package/dist/tools/DeleteDataTool.js +2 -4
- package/dist/tools/DeleteDataTool.js.map +1 -1
- package/dist/tools/DescribeDependenciesTool.js +2 -4
- package/dist/tools/DescribeDependenciesTool.js.map +1 -1
- package/dist/tools/DescribeObjectTool.js +2 -4
- package/dist/tools/DescribeObjectTool.js.map +1 -1
- package/dist/tools/DescribeRelationshipsTool.js +2 -4
- package/dist/tools/DescribeRelationshipsTool.js.map +1 -1
- package/dist/tools/DescribeTableTool.js +2 -4
- package/dist/tools/DescribeTableTool.js.map +1 -1
- package/dist/tools/DropTableTool.js +2 -4
- package/dist/tools/DropTableTool.js.map +1 -1
- package/dist/tools/ExplainQueryTool.d.ts.map +1 -1
- package/dist/tools/ExplainQueryTool.js +4 -6
- package/dist/tools/ExplainQueryTool.js.map +1 -1
- package/dist/tools/InsertDataTool.js +2 -4
- package/dist/tools/InsertDataTool.js.map +1 -1
- package/dist/tools/ListDatabasesTool.js +2 -4
- package/dist/tools/ListDatabasesTool.js.map +1 -1
- package/dist/tools/ListForeignKeysTool.js +2 -4
- package/dist/tools/ListForeignKeysTool.js.map +1 -1
- package/dist/tools/ListLargestTablesTool.js +2 -4
- package/dist/tools/ListLargestTablesTool.js.map +1 -1
- package/dist/tools/ListObjectsTool.js +2 -4
- package/dist/tools/ListObjectsTool.js.map +1 -1
- package/dist/tools/ListTableTool.js +2 -4
- package/dist/tools/ListTableTool.js.map +1 -1
- package/dist/tools/PreviewDeleteTool.js +2 -4
- package/dist/tools/PreviewDeleteTool.js.map +1 -1
- package/dist/tools/PreviewUpdateTool.js +2 -4
- package/dist/tools/PreviewUpdateTool.js.map +1 -1
- package/dist/tools/ReadDataTool.d.ts +15 -12
- package/dist/tools/ReadDataTool.d.ts.map +1 -1
- package/dist/tools/ReadDataTool.js +86 -64
- package/dist/tools/ReadDataTool.js.map +1 -1
- package/dist/tools/SearchDataTool.js +2 -4
- package/dist/tools/SearchDataTool.js.map +1 -1
- package/dist/tools/SummarizeSchemaTool.js +2 -4
- package/dist/tools/SummarizeSchemaTool.js.map +1 -1
- package/dist/tools/UpdateDataTool.js +2 -4
- package/dist/tools/UpdateDataTool.js.map +1 -1
- package/dist/validation.d.ts +26 -3
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +237 -85
- package/dist/validation.js.map +1 -1
- package/dist/writePreview.js +0 -0
- package/dist/writePreviewGrant.js +0 -0
- package/dist/writePreviewGrantStore.js +0 -0
- package/dist/writeSafety.js +0 -0
- package/package.json +29 -22
package/dist/validation.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SQL query validation for read-only operations.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* The query is tokenized following T-SQL lexing rules (string literals,
|
|
5
|
+
* quoted identifiers, nested comments, numeric/hex/money literals, CR or LF
|
|
6
|
+
* line endings) so checks compare whole tokens. This matters because SQL
|
|
7
|
+
* Server splits `1COMMIT` into `1` and `COMMIT` and runs consecutive
|
|
8
|
+
* statements without a separating semicolon; regex word boundaries miss both.
|
|
9
|
+
*
|
|
10
|
+
* Validation is one layer: read_data also runs every query inside a
|
|
11
|
+
* transaction that is always rolled back, and a least-privilege login remains
|
|
12
|
+
* the primary control.
|
|
4
13
|
*/
|
|
5
|
-
const
|
|
14
|
+
const MAX_QUERY_LENGTH = 10000;
|
|
15
|
+
/** Words that never appear in a single read-only SELECT. */
|
|
16
|
+
const DANGEROUS_KEYWORDS = new Set([
|
|
6
17
|
"DELETE",
|
|
7
18
|
"DROP",
|
|
8
19
|
"UPDATE",
|
|
20
|
+
"UPDATETEXT",
|
|
21
|
+
"WRITETEXT",
|
|
9
22
|
"INSERT",
|
|
10
23
|
"ALTER",
|
|
11
24
|
"CREATE",
|
|
@@ -13,121 +26,260 @@ const DANGEROUS_KEYWORDS = [
|
|
|
13
26
|
"EXEC",
|
|
14
27
|
"EXECUTE",
|
|
15
28
|
"MERGE",
|
|
16
|
-
"REPLACE",
|
|
17
29
|
"GRANT",
|
|
18
30
|
"REVOKE",
|
|
31
|
+
"DENY",
|
|
19
32
|
"COMMIT",
|
|
20
33
|
"ROLLBACK",
|
|
34
|
+
"SAVE",
|
|
21
35
|
"TRANSACTION",
|
|
36
|
+
"TRAN",
|
|
22
37
|
"BEGIN",
|
|
23
38
|
"DECLARE",
|
|
24
39
|
"SET",
|
|
40
|
+
"SETUSER",
|
|
41
|
+
"REVERT",
|
|
25
42
|
"USE",
|
|
26
43
|
"BACKUP",
|
|
27
44
|
"RESTORE",
|
|
28
45
|
"KILL",
|
|
29
46
|
"SHUTDOWN",
|
|
47
|
+
"CHECKPOINT",
|
|
48
|
+
"RECONFIGURE",
|
|
49
|
+
"DBCC",
|
|
30
50
|
"WAITFOR",
|
|
51
|
+
"RECEIVE",
|
|
52
|
+
"SEND",
|
|
53
|
+
"MOVE",
|
|
54
|
+
"WHILE",
|
|
55
|
+
"IF",
|
|
56
|
+
"GOTO",
|
|
57
|
+
"RAISERROR",
|
|
58
|
+
"THROW",
|
|
59
|
+
"PRINT",
|
|
31
60
|
"OPENROWSET",
|
|
32
61
|
"OPENDATASOURCE",
|
|
33
62
|
"OPENQUERY",
|
|
34
63
|
"OPENXML",
|
|
35
64
|
"BULK",
|
|
36
65
|
"INTO",
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/HOST_NAME/i,
|
|
56
|
-
/WAITFOR\s+DELAY/i,
|
|
57
|
-
/WAITFOR\s+TIME/i,
|
|
58
|
-
/;\s*\w/,
|
|
59
|
-
/\+\s*CHAR\s*\(/i,
|
|
60
|
-
/\+\s*NCHAR\s*\(/i,
|
|
61
|
-
/\+\s*ASCII\s*\(/i,
|
|
62
|
-
];
|
|
66
|
+
]);
|
|
67
|
+
/** Functions that disclose login or host identity. */
|
|
68
|
+
const IDENTITY_FUNCTIONS = new Set([
|
|
69
|
+
"USER_NAME",
|
|
70
|
+
"SUSER_NAME",
|
|
71
|
+
"SUSER_SNAME",
|
|
72
|
+
"HOST_NAME",
|
|
73
|
+
"ORIGINAL_LOGIN",
|
|
74
|
+
]);
|
|
75
|
+
/** Words that may directly precede an additional top-level SELECT. */
|
|
76
|
+
const SET_OPERATORS = new Set(["UNION", "ALL", "EXCEPT", "INTERSECT"]);
|
|
77
|
+
const WORD_START = /[\p{L}_@#]/u;
|
|
78
|
+
const WORD_PART = /[\p{L}\p{N}_@#$]/u;
|
|
79
|
+
const DIGIT = /[0-9]/;
|
|
80
|
+
const HEX_DIGIT = /[0-9A-Fa-f]/;
|
|
81
|
+
function isLineBreak(char) {
|
|
82
|
+
return char === "\n" || char === "\r";
|
|
83
|
+
}
|
|
63
84
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
85
|
+
* Splits a query into T-SQL tokens. Comments and whitespace are dropped.
|
|
86
|
+
* Returns null when a string literal, quoted identifier, or block comment is
|
|
87
|
+
* left unterminated.
|
|
88
|
+
*/
|
|
89
|
+
export function tokenizeSql(query) {
|
|
90
|
+
const tokens = [];
|
|
91
|
+
let index = 0;
|
|
92
|
+
const readNumber = () => {
|
|
93
|
+
const start = index;
|
|
94
|
+
if (query[index] === "0" && /[xX]/.test(query[index + 1] ?? "")) {
|
|
95
|
+
index += 2;
|
|
96
|
+
while (HEX_DIGIT.test(query[index] ?? ""))
|
|
97
|
+
index += 1;
|
|
98
|
+
return query.slice(start, index);
|
|
99
|
+
}
|
|
100
|
+
while (DIGIT.test(query[index] ?? ""))
|
|
101
|
+
index += 1;
|
|
102
|
+
if (query[index] === ".") {
|
|
103
|
+
index += 1;
|
|
104
|
+
while (DIGIT.test(query[index] ?? ""))
|
|
105
|
+
index += 1;
|
|
106
|
+
}
|
|
107
|
+
if (/[eE]/.test(query[index] ?? "") &&
|
|
108
|
+
(DIGIT.test(query[index + 1] ?? "") ||
|
|
109
|
+
(/[+-]/.test(query[index + 1] ?? "") &&
|
|
110
|
+
DIGIT.test(query[index + 2] ?? "")))) {
|
|
111
|
+
index += 2;
|
|
112
|
+
while (DIGIT.test(query[index] ?? ""))
|
|
113
|
+
index += 1;
|
|
114
|
+
}
|
|
115
|
+
return query.slice(start, index);
|
|
116
|
+
};
|
|
117
|
+
while (index < query.length) {
|
|
118
|
+
const char = query[index];
|
|
119
|
+
const next = query[index + 1];
|
|
120
|
+
if (/\s/.test(char)) {
|
|
121
|
+
index += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// Line comments end at CR or LF: SQL Server treats a bare CR as a break.
|
|
125
|
+
if (char === "-" && next === "-") {
|
|
126
|
+
while (index < query.length && !isLineBreak(query[index]))
|
|
127
|
+
index += 1;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (char === "/" && next === "*") {
|
|
131
|
+
// T-SQL block comments nest.
|
|
132
|
+
let depth = 1;
|
|
133
|
+
index += 2;
|
|
134
|
+
while (index < query.length && depth > 0) {
|
|
135
|
+
if (query[index] === "/" && query[index + 1] === "*") {
|
|
136
|
+
depth += 1;
|
|
137
|
+
index += 2;
|
|
138
|
+
}
|
|
139
|
+
else if (query[index] === "*" && query[index + 1] === "/") {
|
|
140
|
+
depth -= 1;
|
|
141
|
+
index += 2;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
index += 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (depth > 0)
|
|
148
|
+
return null;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (char === "'" || char === '"' || char === "[") {
|
|
152
|
+
const close = char === "[" ? "]" : char;
|
|
153
|
+
const start = index;
|
|
154
|
+
index += 1;
|
|
155
|
+
let terminated = false;
|
|
156
|
+
while (index < query.length) {
|
|
157
|
+
if (query[index] === close) {
|
|
158
|
+
// Doubled delimiters ('' or ]] or "") escape the delimiter.
|
|
159
|
+
if (query[index + 1] === close) {
|
|
160
|
+
index += 2;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
index += 1;
|
|
164
|
+
terminated = true;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
index += 1;
|
|
168
|
+
}
|
|
169
|
+
if (!terminated)
|
|
170
|
+
return null;
|
|
171
|
+
tokens.push({
|
|
172
|
+
type: char === "'" ? "string" : "identifier",
|
|
173
|
+
value: query.slice(start, index),
|
|
174
|
+
});
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (DIGIT.test(char) || (char === "." && DIGIT.test(next ?? ""))) {
|
|
178
|
+
tokens.push({ type: "number", value: readNumber() });
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// Money literal such as $5 or $.5.
|
|
182
|
+
if (char === "$" &&
|
|
183
|
+
(DIGIT.test(next ?? "") ||
|
|
184
|
+
(next === "." && DIGIT.test(query[index + 2] ?? "")))) {
|
|
185
|
+
index += 1;
|
|
186
|
+
tokens.push({ type: "number", value: `$${readNumber()}` });
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (WORD_START.test(char) ||
|
|
190
|
+
(char === "$" && WORD_START.test(next ?? ""))) {
|
|
191
|
+
const start = index;
|
|
192
|
+
index += 1;
|
|
193
|
+
while (index < query.length && WORD_PART.test(query[index]))
|
|
194
|
+
index += 1;
|
|
195
|
+
tokens.push({
|
|
196
|
+
type: "word",
|
|
197
|
+
value: query.slice(start, index).toUpperCase(),
|
|
198
|
+
});
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
tokens.push({ type: "punct", value: char });
|
|
202
|
+
index += 1;
|
|
203
|
+
}
|
|
204
|
+
return tokens;
|
|
205
|
+
}
|
|
206
|
+
function invalid(error) {
|
|
207
|
+
return { isValid: false, error };
|
|
208
|
+
}
|
|
209
|
+
const MALICIOUS_PATTERN_ERROR = "Potentially malicious SQL pattern detected. Only simple SELECT queries are allowed.";
|
|
210
|
+
/**
|
|
211
|
+
* Validates a SQL query for read-only use: exactly one SELECT statement,
|
|
212
|
+
* optionally preceded by common table expressions and combined with
|
|
213
|
+
* UNION/EXCEPT/INTERSECT.
|
|
66
214
|
*/
|
|
67
215
|
export function validateReadQuery(query) {
|
|
68
216
|
if (!query || typeof query !== "string") {
|
|
69
|
-
return
|
|
70
|
-
isValid: false,
|
|
71
|
-
error: "Query must be a non-empty string",
|
|
72
|
-
};
|
|
217
|
+
return invalid("Query must be a non-empty string");
|
|
73
218
|
}
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
77
|
-
.replace(/\s+/g, " ")
|
|
78
|
-
.trim();
|
|
79
|
-
if (!cleanQuery) {
|
|
80
|
-
return {
|
|
81
|
-
isValid: false,
|
|
82
|
-
error: "Query cannot be empty after removing comments",
|
|
83
|
-
};
|
|
219
|
+
if (query.length > MAX_QUERY_LENGTH) {
|
|
220
|
+
return invalid("Query is too long. Maximum allowed length is 10,000 characters.");
|
|
84
221
|
}
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
return
|
|
88
|
-
isValid: false,
|
|
89
|
-
error: "Query must start with SELECT for security reasons",
|
|
90
|
-
};
|
|
222
|
+
const tokens = tokenizeSql(query);
|
|
223
|
+
if (tokens === null) {
|
|
224
|
+
return invalid("Query contains an unterminated string literal, quoted identifier, or comment.");
|
|
91
225
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
226
|
+
// Leading and trailing semicolons are harmless (";WITH ..." style, "...;").
|
|
227
|
+
let start = 0;
|
|
228
|
+
let end = tokens.length;
|
|
229
|
+
while (start < end && tokens[start].value === ";")
|
|
230
|
+
start += 1;
|
|
231
|
+
while (end > start && tokens[end - 1].value === ";")
|
|
232
|
+
end -= 1;
|
|
233
|
+
const body = tokens.slice(start, end);
|
|
234
|
+
if (body.length === 0) {
|
|
235
|
+
return invalid("Query cannot be empty after removing comments");
|
|
236
|
+
}
|
|
237
|
+
if (body[0].type !== "word" || !["SELECT", "WITH"].includes(body[0].value)) {
|
|
238
|
+
return invalid("Query must start with SELECT (or WITH for a CTE)");
|
|
100
239
|
}
|
|
101
|
-
for (const
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
240
|
+
for (const [position, token] of body.entries()) {
|
|
241
|
+
if (token.type !== "word")
|
|
242
|
+
continue;
|
|
243
|
+
if (DANGEROUS_KEYWORDS.has(token.value)) {
|
|
244
|
+
return invalid(`Dangerous keyword '${token.value}' detected in query. Only SELECT operations are allowed.`);
|
|
245
|
+
}
|
|
246
|
+
const following = body[position + 1];
|
|
247
|
+
if (token.value.startsWith("@@") ||
|
|
248
|
+
token.value.startsWith("SP_") ||
|
|
249
|
+
token.value.startsWith("XP_") ||
|
|
250
|
+
token.value === "SYSTEM_USER" ||
|
|
251
|
+
(IDENTITY_FUNCTIONS.has(token.value) && following?.value === "(") ||
|
|
252
|
+
((token.value === "ENABLE" || token.value === "DISABLE") &&
|
|
253
|
+
following?.value === "TRIGGER") ||
|
|
254
|
+
((token.value === "END" || token.value === "GET") &&
|
|
255
|
+
following?.value === "CONVERSATION")) {
|
|
256
|
+
return invalid(MALICIOUS_PATTERN_ERROR);
|
|
107
257
|
}
|
|
108
258
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.filter((stmt) => stmt.trim().length > 0);
|
|
112
|
-
if (statements.length > 1) {
|
|
113
|
-
return {
|
|
114
|
-
isValid: false,
|
|
115
|
-
error: "Multiple SQL statements are not allowed. Use only a single SELECT statement.",
|
|
116
|
-
};
|
|
259
|
+
if (body.some((token) => token.value === ";")) {
|
|
260
|
+
return invalid("Multiple SQL statements are not allowed. Use only a single SELECT statement.");
|
|
117
261
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
262
|
+
// SQL Server runs consecutive statements without a separating semicolon,
|
|
263
|
+
// so count top-level SELECTs that are not arms of a set operation.
|
|
264
|
+
let depth = 0;
|
|
265
|
+
let statementSelects = 0;
|
|
266
|
+
for (const [position, token] of body.entries()) {
|
|
267
|
+
if (token.value === "(")
|
|
268
|
+
depth += 1;
|
|
269
|
+
else if (token.value === ")")
|
|
270
|
+
depth -= 1;
|
|
271
|
+
else if (token.type === "word" && token.value === "SELECT" && depth === 0) {
|
|
272
|
+
const previous = body[position - 1];
|
|
273
|
+
if (!previous || !SET_OPERATORS.has(previous.value)) {
|
|
274
|
+
statementSelects += 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (depth < 0) {
|
|
278
|
+
return invalid("Query has unbalanced parentheses.");
|
|
279
|
+
}
|
|
125
280
|
}
|
|
126
|
-
if (
|
|
127
|
-
return
|
|
128
|
-
isValid: false,
|
|
129
|
-
error: "Query is too long. Maximum allowed length is 10,000 characters.",
|
|
130
|
-
};
|
|
281
|
+
if (statementSelects !== 1) {
|
|
282
|
+
return invalid("Multiple SQL statements are not allowed. Use only a single SELECT statement.");
|
|
131
283
|
}
|
|
132
284
|
return { isValid: true };
|
|
133
285
|
}
|
package/dist/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/dist/writePreview.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/writeSafety.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eamonboyle/mssql-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "MCP server for Microsoft SQL Server - query and manage your database with natural language in Cursor, Claude, and VS Code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -30,45 +30,52 @@
|
|
|
30
30
|
"mssql-mcp": "dist/index.js"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
|
-
"build": "
|
|
33
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc && node -e \"require('fs').chmodSync('dist/index.js',0o755)\"",
|
|
34
34
|
"prepare": "npm run build",
|
|
35
35
|
"watch": "tsc --watch",
|
|
36
36
|
"start": "node dist/index.js",
|
|
37
37
|
"test": "vitest run",
|
|
38
38
|
"test:watch": "vitest",
|
|
39
|
-
"lint": "eslint src",
|
|
40
|
-
"format": "prettier --write src",
|
|
41
|
-
"docs:check-install-links": "node scripts/generate-install-links.mjs --check",
|
|
42
|
-
"docs:update-install-links": "node scripts/generate-install-links.mjs",
|
|
39
|
+
"lint": "eslint src",
|
|
40
|
+
"format": "prettier --write src",
|
|
41
|
+
"docs:check-install-links": "node scripts/generate-install-links.mjs --check",
|
|
42
|
+
"docs:update-install-links": "node scripts/generate-install-links.mjs",
|
|
43
43
|
"db:up": "bash scripts/mssql-up.sh",
|
|
44
44
|
"db:down": "bash scripts/mssql-down.sh",
|
|
45
45
|
"db:seed": "bash scripts/mssql-seed.sh",
|
|
46
46
|
"db:reset": "bash scripts/mssql-down.sh --volumes && bash scripts/mssql-up.sh",
|
|
47
|
-
"test:e2e": "bash scripts/e2e-mcp-tools.sh"
|
|
47
|
+
"test:e2e": "bash scripts/e2e-mcp-tools.sh && node scripts/e2e-protocol.mjs",
|
|
48
|
+
"test:e2e:protocol": "node scripts/e2e-protocol.mjs"
|
|
48
49
|
},
|
|
49
50
|
"files": [
|
|
50
51
|
"dist"
|
|
51
52
|
],
|
|
52
53
|
"engines": {
|
|
53
|
-
"node": ">=
|
|
54
|
+
"node": ">=22.0.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "^
|
|
57
|
-
"@
|
|
58
|
-
"@types/
|
|
59
|
-
"
|
|
57
|
+
"@eslint/js": "^10.0.1",
|
|
58
|
+
"@modelcontextprotocol/client": "^2.3.1",
|
|
59
|
+
"@types/mssql": "^12.3.0",
|
|
60
|
+
"@types/node": "^22.20.5",
|
|
61
|
+
"eslint": "^10.12.0",
|
|
60
62
|
"eslint-config-prettier": "^10.1.8",
|
|
61
|
-
"prettier": "^3.
|
|
62
|
-
"
|
|
63
|
-
"typescript": "
|
|
64
|
-
"typescript-eslint": "^8.
|
|
65
|
-
"vitest": "^
|
|
63
|
+
"prettier": "^3.9.10",
|
|
64
|
+
"sprintf-js": "file:vendor/sprintf-js",
|
|
65
|
+
"typescript": "~6.0.3",
|
|
66
|
+
"typescript-eslint": "^8.71.1",
|
|
67
|
+
"vitest": "^5.0.3"
|
|
66
68
|
},
|
|
67
69
|
"dependencies": {
|
|
68
|
-
"@modelcontextprotocol/
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
70
|
+
"@modelcontextprotocol/ext-apps": "^2.0.3",
|
|
71
|
+
"@modelcontextprotocol/node": "^2.1.1",
|
|
72
|
+
"@modelcontextprotocol/server": "^2.3.1",
|
|
73
|
+
"dotenv": "^18.0.7",
|
|
74
|
+
"mssql": "^12.7.4",
|
|
75
|
+
"zod": "^4.6.5"
|
|
72
76
|
},
|
|
73
|
-
"type": "module"
|
|
77
|
+
"type": "module",
|
|
78
|
+
"overrides": {
|
|
79
|
+
"sprintf-js": "$sprintf-js"
|
|
80
|
+
}
|
|
74
81
|
}
|