@connorbritain/mssql-mcp-server 0.3.5 → 0.4.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 (99) hide show
  1. package/dist/index.js +6 -747
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -5
  4. package/dist/audit/AuditLogger.d.ts +0 -37
  5. package/dist/audit/AuditLogger.d.ts.map +0 -1
  6. package/dist/audit/AuditLogger.js +0 -145
  7. package/dist/audit/AuditLogger.js.map +0 -1
  8. package/dist/config/EnvironmentManager.d.ts +0 -75
  9. package/dist/config/EnvironmentManager.d.ts.map +0 -1
  10. package/dist/config/EnvironmentManager.js +0 -297
  11. package/dist/config/EnvironmentManager.js.map +0 -1
  12. package/dist/config/ScriptManager.d.ts +0 -69
  13. package/dist/config/ScriptManager.d.ts.map +0 -1
  14. package/dist/config/ScriptManager.js +0 -166
  15. package/dist/config/ScriptManager.js.map +0 -1
  16. package/dist/config/SecretResolver.d.ts +0 -66
  17. package/dist/config/SecretResolver.d.ts.map +0 -1
  18. package/dist/config/SecretResolver.js +0 -230
  19. package/dist/config/SecretResolver.js.map +0 -1
  20. package/dist/tools/CreateIndexTool.d.ts +0 -24
  21. package/dist/tools/CreateIndexTool.d.ts.map +0 -1
  22. package/dist/tools/CreateIndexTool.js +0 -64
  23. package/dist/tools/CreateIndexTool.js.map +0 -1
  24. package/dist/tools/CreateTableTool.d.ts +0 -12
  25. package/dist/tools/CreateTableTool.d.ts.map +0 -1
  26. package/dist/tools/CreateTableTool.js +0 -49
  27. package/dist/tools/CreateTableTool.js.map +0 -1
  28. package/dist/tools/DeleteDataTool.d.ts +0 -56
  29. package/dist/tools/DeleteDataTool.d.ts.map +0 -1
  30. package/dist/tools/DeleteDataTool.js +0 -103
  31. package/dist/tools/DeleteDataTool.js.map +0 -1
  32. package/dist/tools/DescribeTableTool.d.ts +0 -32
  33. package/dist/tools/DescribeTableTool.d.ts.map +0 -1
  34. package/dist/tools/DescribeTableTool.js +0 -108
  35. package/dist/tools/DescribeTableTool.js.map +0 -1
  36. package/dist/tools/DropTableTool.d.ts +0 -12
  37. package/dist/tools/DropTableTool.d.ts.map +0 -1
  38. package/dist/tools/DropTableTool.js +0 -37
  39. package/dist/tools/DropTableTool.js.map +0 -1
  40. package/dist/tools/ExplainQueryTool.d.ts +0 -24
  41. package/dist/tools/ExplainQueryTool.d.ts.map +0 -1
  42. package/dist/tools/ExplainQueryTool.js +0 -98
  43. package/dist/tools/ExplainQueryTool.js.map +0 -1
  44. package/dist/tools/InsertDataTool.d.ts +0 -17
  45. package/dist/tools/InsertDataTool.d.ts.map +0 -1
  46. package/dist/tools/InsertDataTool.js +0 -102
  47. package/dist/tools/InsertDataTool.js.map +0 -1
  48. package/dist/tools/InspectDependenciesTool.d.ts +0 -45
  49. package/dist/tools/InspectDependenciesTool.d.ts.map +0 -1
  50. package/dist/tools/InspectDependenciesTool.js +0 -215
  51. package/dist/tools/InspectDependenciesTool.js.map +0 -1
  52. package/dist/tools/ListDatabasesTool.d.ts +0 -27
  53. package/dist/tools/ListDatabasesTool.d.ts.map +0 -1
  54. package/dist/tools/ListDatabasesTool.js +0 -107
  55. package/dist/tools/ListDatabasesTool.js.map +0 -1
  56. package/dist/tools/ListEnvironmentsTool.d.ts +0 -49
  57. package/dist/tools/ListEnvironmentsTool.d.ts.map +0 -1
  58. package/dist/tools/ListEnvironmentsTool.js +0 -73
  59. package/dist/tools/ListEnvironmentsTool.js.map +0 -1
  60. package/dist/tools/ListScriptsTool.d.ts +0 -41
  61. package/dist/tools/ListScriptsTool.d.ts.map +0 -1
  62. package/dist/tools/ListScriptsTool.js +0 -86
  63. package/dist/tools/ListScriptsTool.js.map +0 -1
  64. package/dist/tools/ListTableTool.d.ts +0 -24
  65. package/dist/tools/ListTableTool.d.ts.map +0 -1
  66. package/dist/tools/ListTableTool.js +0 -85
  67. package/dist/tools/ListTableTool.js.map +0 -1
  68. package/dist/tools/ProfileTableTool.d.ts +0 -78
  69. package/dist/tools/ProfileTableTool.d.ts.map +0 -1
  70. package/dist/tools/ProfileTableTool.js +0 -373
  71. package/dist/tools/ProfileTableTool.js.map +0 -1
  72. package/dist/tools/ReadDataTool.d.ts +0 -61
  73. package/dist/tools/ReadDataTool.d.ts.map +0 -1
  74. package/dist/tools/ReadDataTool.js +0 -299
  75. package/dist/tools/ReadDataTool.js.map +0 -1
  76. package/dist/tools/RelationshipInspectorTool.d.ts +0 -46
  77. package/dist/tools/RelationshipInspectorTool.d.ts.map +0 -1
  78. package/dist/tools/RelationshipInspectorTool.js +0 -156
  79. package/dist/tools/RelationshipInspectorTool.js.map +0 -1
  80. package/dist/tools/RunScriptTool.d.ts +0 -215
  81. package/dist/tools/RunScriptTool.d.ts.map +0 -1
  82. package/dist/tools/RunScriptTool.js +0 -177
  83. package/dist/tools/RunScriptTool.js.map +0 -1
  84. package/dist/tools/SearchSchemaTool.d.ts +0 -88
  85. package/dist/tools/SearchSchemaTool.d.ts.map +0 -1
  86. package/dist/tools/SearchSchemaTool.js +0 -237
  87. package/dist/tools/SearchSchemaTool.js.map +0 -1
  88. package/dist/tools/TestConnectionTool.d.ts +0 -36
  89. package/dist/tools/TestConnectionTool.d.ts.map +0 -1
  90. package/dist/tools/TestConnectionTool.js +0 -155
  91. package/dist/tools/TestConnectionTool.js.map +0 -1
  92. package/dist/tools/UpdateDataTool.d.ts +0 -61
  93. package/dist/tools/UpdateDataTool.d.ts.map +0 -1
  94. package/dist/tools/UpdateDataTool.js +0 -117
  95. package/dist/tools/UpdateDataTool.js.map +0 -1
  96. package/dist/tools/ValidateEnvironmentConfigTool.d.ts +0 -51
  97. package/dist/tools/ValidateEnvironmentConfigTool.d.ts.map +0 -1
  98. package/dist/tools/ValidateEnvironmentConfigTool.js +0 -320
  99. package/dist/tools/ValidateEnvironmentConfigTool.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,752 +1,11 @@
1
1
  #!/usr/bin/env node
2
- // External imports
3
- import { Buffer } from "node:buffer";
4
- import * as dotenv from "dotenv";
5
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
- import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
8
- // Node 21+ dropped the legacy global SlowBuffer. Some transitive deps (jsonwebtoken)
9
- // still reference it, so reintroduce a shim to keep compatibility with latest Node.
10
- if (!globalThis.SlowBuffer) {
11
- globalThis.SlowBuffer = Buffer.allocUnsafeSlow;
12
- }
13
- dotenv.config();
14
- // Internal imports
15
- import { UpdateDataTool } from "./tools/UpdateDataTool.js";
16
- import { InsertDataTool } from "./tools/InsertDataTool.js";
17
- import { ReadDataTool } from "./tools/ReadDataTool.js";
18
- import { CreateTableTool } from "./tools/CreateTableTool.js";
19
- import { CreateIndexTool } from "./tools/CreateIndexTool.js";
20
- import { ListTableTool } from "./tools/ListTableTool.js";
21
- import { DropTableTool } from "./tools/DropTableTool.js";
22
- import { TestConnectionTool } from "./tools/TestConnectionTool.js";
23
- import { DeleteDataTool } from "./tools/DeleteDataTool.js";
24
- import { DescribeTableTool } from "./tools/DescribeTableTool.js";
25
- import { SearchSchemaTool } from "./tools/SearchSchemaTool.js";
26
- import { ProfileTableTool } from "./tools/ProfileTableTool.js";
27
- import { RelationshipInspectorTool } from "./tools/RelationshipInspectorTool.js";
28
- import { ExplainQueryTool } from "./tools/ExplainQueryTool.js";
29
- import { ListDatabasesTool } from "./tools/ListDatabasesTool.js";
30
- import { ListEnvironmentsTool } from "./tools/ListEnvironmentsTool.js";
31
- import { ValidateEnvironmentConfigTool } from "./tools/ValidateEnvironmentConfigTool.js";
32
- import { ListScriptsTool } from "./tools/ListScriptsTool.js";
33
- import { RunScriptTool } from "./tools/RunScriptTool.js";
34
- import { InspectDependenciesTool } from "./tools/InspectDependenciesTool.js";
35
- import { auditLogger } from "./audit/AuditLogger.js";
36
- import { getEnvironmentManager } from "./config/EnvironmentManager.js";
37
- import * as crypto from "crypto";
38
- // Generate a unique session ID for this server instance
39
- // This allows correlation of all tool invocations within a single MCP session
40
- const SESSION_ID = crypto.randomUUID();
41
- class IntentRouter {
42
- constructor(options) {
43
- this.tools = options.tools;
44
- this.allowMutations = options.allowMutations;
45
- this.requireConfirmationForMutations = options.requireConfirmationForMutations;
46
- }
47
- async route(params) {
48
- const prompt = typeof params.prompt === "string" ? params.prompt.trim() : "";
49
- if (!prompt) {
50
- return {
51
- success: false,
52
- message: "Prompt is required to route intent.",
53
- error: "MISSING_PROMPT",
54
- };
55
- }
56
- const toolArguments = this.normalizeArguments(params.toolArguments ?? {});
57
- const confirmIntent = Boolean(params.confirmIntent);
58
- const preferredToolName = params.preferredToolName;
59
- const normalizedPrompt = prompt.toLowerCase();
60
- // Infer environment from prompt if not explicitly provided
61
- const environment = params.environment || this.inferEnvironment(normalizedPrompt);
62
- if (environment) {
63
- toolArguments.environment = environment;
64
- }
65
- const inferredIntent = this.inferIntent(normalizedPrompt, toolArguments);
66
- const eligibleTools = this.tools.filter((tool) => this.isToolEligible(tool));
67
- const candidates = eligibleTools
68
- .map((tool) => this.scoreTool(tool, normalizedPrompt, toolArguments, inferredIntent, preferredToolName))
69
- .filter((candidate) => candidate.score > Number.NEGATIVE_INFINITY)
70
- .sort((a, b) => b.score - a.score);
71
- const bestCandidate = candidates[0];
72
- if (!bestCandidate || bestCandidate.score <= 0) {
73
- return {
74
- success: false,
75
- message: "Unable to determine an appropriate SQL tool for the provided prompt. Try specifying the desired action more concretely (e.g., 'list tables', 'describe table X', 'run SELECT ...').",
76
- error: "NO_TOOL_MATCH",
77
- };
78
- }
79
- const missingArgs = this.getMissingArguments(bestCandidate.config, toolArguments);
80
- if (missingArgs.length) {
81
- return {
82
- success: false,
83
- routedTool: bestCandidate.config.name,
84
- message: `Selected tool '${bestCandidate.config.name}' requires argument(s): ${missingArgs.join(", ")}. Provide them in the request arguments.`,
85
- error: "MISSING_ARGUMENTS",
86
- };
87
- }
88
- const requiresConfirmation = (bestCandidate.config.requiresConfirmation ||
89
- bestCandidate.config.mutatesData ||
90
- bestCandidate.config.schemaChange) &&
91
- this.requireConfirmationForMutations;
92
- if (requiresConfirmation && !confirmIntent) {
93
- return {
94
- success: false,
95
- routedTool: bestCandidate.config.name,
96
- message: "This operation modifies data or schema. Re-run with confirmIntent: true to proceed.",
97
- error: "CONFIRMATION_REQUIRED",
98
- };
99
- }
100
- try {
101
- const result = await bestCandidate.config.tool.run(toolArguments);
102
- return {
103
- success: true,
104
- routedTool: bestCandidate.config.name,
105
- intent: inferredIntent,
106
- reasoning: bestCandidate.reasons,
107
- toolResult: result,
108
- selectedEnvironment: environment,
109
- };
110
- }
111
- catch (error) {
112
- return {
113
- success: false,
114
- routedTool: bestCandidate.config.name,
115
- message: `Routed tool '${bestCandidate.config.name}' failed: ${error}`,
116
- error: "ROUTED_TOOL_FAILED",
117
- selectedEnvironment: environment,
118
- };
119
- }
120
- }
121
- inferEnvironment(prompt) {
122
- // Get available environments from the manager
123
- const envManager = getEnvironmentManager();
124
- const environments = envManager.listEnvironments();
125
- // Look for exact environment name mentions
126
- for (const env of environments) {
127
- const patterns = [
128
- new RegExp(`\\b${env.name}\\b`, "i"),
129
- new RegExp(`\\b${env.name.replace(/-/g, "\\s")}\\b`, "i"), // Handle dashes as spaces
130
- ];
131
- for (const pattern of patterns) {
132
- if (pattern.test(prompt)) {
133
- return env.name;
134
- }
135
- }
136
- }
137
- // Look for common environment keywords
138
- const envKeywords = {
139
- prod: ["production", "prod", "live"],
140
- staging: ["staging", "stage", "uat"],
141
- dev: ["development", "dev", "local"],
142
- };
143
- for (const [envSuffix, keywords] of Object.entries(envKeywords)) {
144
- for (const keyword of keywords) {
145
- if (prompt.includes(keyword)) {
146
- // Try to find an environment with this suffix
147
- const matchingEnv = environments.find((e) => e.name.toLowerCase().includes(envSuffix));
148
- if (matchingEnv) {
149
- return matchingEnv.name;
150
- }
151
- }
152
- }
153
- }
154
- // No environment inferred, will use default
155
- return undefined;
156
- }
157
- normalizeArguments(args) {
158
- if (!args || typeof args !== "object") {
159
- return {};
160
- }
161
- const cloned = {};
162
- for (const [key, value] of Object.entries(args)) {
163
- if (value !== undefined) {
164
- cloned[key] = value;
165
- }
166
- }
167
- return cloned;
168
- }
169
- isToolEligible(tool) {
170
- if (this.allowMutations) {
171
- return true;
172
- }
173
- return !tool.mutatesData && !tool.schemaChange;
174
- }
175
- inferIntent(prompt, toolArguments) {
176
- const detectors = [
177
- {
178
- intent: "schema_change",
179
- keywords: ["create table", "drop table", "create index", "drop index", "alter", "ddl"],
180
- },
181
- {
182
- intent: "data_write",
183
- keywords: ["update", "insert", "delete", "fix", "modify", "change", "correct"],
184
- },
185
- {
186
- intent: "metadata",
187
- keywords: ["profile", "sample", "statistics", "distribution", "quality"],
188
- },
189
- {
190
- intent: "schema_discovery",
191
- keywords: ["describe", "columns", "list tables", "show tables", "schema", "search"],
192
- },
193
- {
194
- intent: "data_read",
195
- keywords: ["select", "query", "fetch", "count", "report", "view"],
196
- },
197
- ];
198
- for (const detector of detectors) {
199
- if (detector.keywords.some((keyword) => prompt.includes(keyword))) {
200
- return detector.intent;
201
- }
202
- }
203
- const sqlSnippet = this.extractSqlSnippet(toolArguments);
204
- if (sqlSnippet) {
205
- if (sqlSnippet.startsWith("select")) {
206
- return "data_read";
207
- }
208
- if (sqlSnippet.startsWith("update") || sqlSnippet.startsWith("delete")) {
209
- return "data_write";
210
- }
211
- if (sqlSnippet.startsWith("insert")) {
212
- return "data_write";
213
- }
214
- if (sqlSnippet.startsWith("create") || sqlSnippet.startsWith("drop")) {
215
- return "schema_change";
216
- }
217
- }
218
- if (toolArguments?.tablePattern || toolArguments?.columnPattern) {
219
- return "schema_discovery";
220
- }
221
- return "data_read";
222
- }
223
- extractSqlSnippet(args) {
224
- const sqlCandidate = typeof args?.query === "string" ? args.query : typeof args?.sql === "string" ? args.sql : null;
225
- return sqlCandidate?.trim().toLowerCase() ?? null;
226
- }
227
- scoreTool(config, prompt, toolArguments, inferredIntent, preferredToolName) {
228
- let score = config.baseScore ?? 0.5;
229
- const reasons = [];
230
- if (config.intents.includes(inferredIntent)) {
231
- score += 5;
232
- reasons.push(`intent match (${inferredIntent})`);
233
- }
234
- if (preferredToolName && config.name === preferredToolName) {
235
- score += 3;
236
- reasons.push("preferred tool match");
237
- }
238
- if (config.keywords?.length) {
239
- for (const keyword of config.keywords) {
240
- if (prompt.includes(keyword)) {
241
- score += 2;
242
- reasons.push(`keyword '${keyword}'`);
243
- }
244
- }
245
- }
246
- if (config.requiredArgs?.length) {
247
- for (const arg of config.requiredArgs) {
248
- if (this.hasArgument(toolArguments, arg)) {
249
- score += 1;
250
- }
251
- else {
252
- score -= 1;
253
- }
254
- }
255
- }
256
- if ((config.mutatesData || config.schemaChange) && !this.allowMutations) {
257
- score = Number.NEGATIVE_INFINITY;
258
- }
259
- return { config, score, reasons };
260
- }
261
- hasArgument(args, key) {
262
- if (!args) {
263
- return false;
264
- }
265
- const value = args[key];
266
- if (value === null || value === undefined) {
267
- return false;
268
- }
269
- if (typeof value === "string") {
270
- return value.trim().length > 0;
271
- }
272
- if (Array.isArray(value)) {
273
- return value.length > 0;
274
- }
275
- if (typeof value === "object") {
276
- return Object.keys(value).length > 0;
277
- }
278
- return true;
279
- }
280
- getMissingArguments(config, args) {
281
- if (!config.requiredArgs || config.requiredArgs.length === 0) {
282
- return [];
283
- }
284
- return config.requiredArgs.filter((arg) => !this.hasArgument(args, arg));
285
- }
286
- }
287
- // ─────────────────────────────────────────────────────────────────────────────
288
- // Initialize environment manager
289
- const environmentManager = getEnvironmentManager();
290
- const updateDataTool = new UpdateDataTool();
291
- const insertDataTool = new InsertDataTool();
292
- const deleteDataTool = new DeleteDataTool();
293
- const readDataTool = new ReadDataTool();
294
- const createTableTool = new CreateTableTool();
295
- const createIndexTool = new CreateIndexTool();
296
- const listTableTool = new ListTableTool();
297
- const listDatabasesTool = new ListDatabasesTool();
298
- const listEnvironmentsTool = new ListEnvironmentsTool();
299
- const validateEnvironmentConfigTool = new ValidateEnvironmentConfigTool();
300
- const listScriptsTool = new ListScriptsTool();
301
- const runScriptTool = new RunScriptTool();
302
- const inspectDependenciesTool = new InspectDependenciesTool();
303
- const dropTableTool = new DropTableTool();
304
- const describeTableTool = new DescribeTableTool();
305
- const searchSchemaTool = new SearchSchemaTool();
306
- const profileTableTool = new ProfileTableTool();
307
- const relationshipInspectorTool = new RelationshipInspectorTool();
308
- const testConnectionTool = new TestConnectionTool();
309
- const explainQueryTool = new ExplainQueryTool();
310
- const MUTATING_TOOL_NAMES = new Set([
311
- "insert_data",
312
- "delete_data",
313
- "update_data",
314
- "create_table",
315
- "create_index",
316
- "drop_table",
317
- ]);
318
- const toolRegistry = [
319
- {
320
- tool: readDataTool,
321
- name: readDataTool.name,
322
- intents: ["data_read"],
323
- keywords: ["select", "query", "fetch", "report", "count"],
324
- requiredArgs: ["query"],
325
- baseScore: 2,
326
- },
327
- {
328
- tool: listTableTool,
329
- name: listTableTool.name,
330
- intents: ["schema_discovery"],
331
- keywords: ["list tables", "show tables", "tables"],
332
- baseScore: 1.5,
333
- },
334
- {
335
- tool: describeTableTool,
336
- name: describeTableTool.name,
337
- intents: ["schema_discovery"],
338
- keywords: ["describe", "columns", "structure"],
339
- requiredArgs: ["tableName"],
340
- baseScore: 1.5,
341
- },
342
- {
343
- tool: searchSchemaTool,
344
- name: searchSchemaTool.name,
345
- intents: ["schema_discovery"],
346
- keywords: ["search", "find", "look up"],
347
- baseScore: 1.5,
348
- },
349
- {
350
- tool: profileTableTool,
351
- name: profileTableTool.name,
352
- intents: ["metadata"],
353
- keywords: ["profile", "sample", "distribution"],
354
- requiredArgs: ["tableName"],
355
- },
356
- {
357
- tool: relationshipInspectorTool,
358
- name: relationshipInspectorTool.name,
359
- intents: ["metadata", "schema_discovery"],
360
- keywords: ["relationships", "foreign key", "references"],
361
- requiredArgs: ["tableName"],
362
- },
363
- {
364
- tool: insertDataTool,
365
- name: insertDataTool.name,
366
- intents: ["data_write"],
367
- keywords: ["insert", "add", "create record"],
368
- requiredArgs: ["tableName", "data"],
369
- mutatesData: true,
370
- },
371
- {
372
- tool: deleteDataTool,
373
- name: deleteDataTool.name,
374
- intents: ["data_write"],
375
- keywords: ["delete", "remove", "purge"],
376
- requiredArgs: ["tableName", "whereClause"],
377
- mutatesData: true,
378
- },
379
- {
380
- tool: updateDataTool,
381
- name: updateDataTool.name,
382
- intents: ["data_write"],
383
- keywords: ["update", "modify", "fix"],
384
- requiredArgs: ["tableName", "updates", "whereClause"],
385
- mutatesData: true,
386
- },
387
- {
388
- tool: createTableTool,
389
- name: createTableTool.name,
390
- intents: ["schema_change"],
391
- keywords: ["create table", "new table"],
392
- requiredArgs: ["tableName", "columns"],
393
- schemaChange: true,
394
- },
395
- {
396
- tool: createIndexTool,
397
- name: createIndexTool.name,
398
- intents: ["schema_change"],
399
- keywords: ["create index", "add index"],
400
- requiredArgs: ["tableName", "columns", "indexName"],
401
- schemaChange: true,
402
- },
403
- {
404
- tool: dropTableTool,
405
- name: dropTableTool.name,
406
- intents: ["schema_change"],
407
- keywords: ["drop table", "remove table", "delete table"],
408
- requiredArgs: ["tableName"],
409
- schemaChange: true,
410
- mutatesData: true,
411
- },
412
- {
413
- tool: testConnectionTool,
414
- name: testConnectionTool.name,
415
- intents: ["metadata"],
416
- keywords: ["test", "connection", "ping", "health"],
417
- baseScore: 1,
418
- },
419
- {
420
- tool: explainQueryTool,
421
- name: explainQueryTool.name,
422
- intents: ["metadata"],
423
- keywords: ["plan", "explain", "showplan", "estimate"],
424
- requiredArgs: ["query"],
425
- baseScore: 1,
426
- },
427
- {
428
- tool: listDatabasesTool,
429
- name: listDatabasesTool.name,
430
- intents: ["schema_discovery", "metadata"],
431
- keywords: ["databases", "list databases", "show databases", "dbs"],
432
- baseScore: 1.5,
433
- },
434
- {
435
- tool: listEnvironmentsTool,
436
- name: listEnvironmentsTool.name,
437
- intents: ["metadata"],
438
- keywords: ["environments", "list environments", "connections", "configs"],
439
- baseScore: 1.5,
440
- },
441
- {
442
- tool: validateEnvironmentConfigTool,
443
- name: validateEnvironmentConfigTool.name,
444
- intents: ["metadata"],
445
- keywords: ["validate", "check", "config", "configuration", "health"],
446
- baseScore: 1.5,
447
- },
448
- {
449
- tool: listScriptsTool,
450
- name: listScriptsTool.name,
451
- intents: ["metadata"],
452
- keywords: ["scripts", "list scripts", "templates", "named scripts"],
453
- baseScore: 1.5,
454
- },
455
- {
456
- tool: runScriptTool,
457
- name: runScriptTool.name,
458
- intents: ["data_read", "data_write"],
459
- keywords: ["run script", "execute script", "template"],
460
- requiredArgs: ["scriptName"],
461
- baseScore: 1.5,
462
- },
463
- {
464
- tool: inspectDependenciesTool,
465
- name: inspectDependenciesTool.name,
466
- intents: ["schema_discovery", "metadata"],
467
- keywords: ["dependencies", "depends", "references", "impact", "what uses"],
468
- requiredArgs: ["objectName"],
469
- baseScore: 1.5,
470
- },
471
- ];
472
- const server = new Server({
2
+ import { startMcpServer } from "@connorbritain/mssql-mcp-core";
3
+ startMcpServer({
473
4
  name: "mssql-mcp-server",
474
- version: "0.1.0",
475
- }, {
476
- capabilities: {
477
- tools: {},
478
- },
479
- });
480
- // Read READONLY env variable
481
- const isReadOnly = process.env.READONLY === "true";
482
- const requireMutationConfirmation = process.env.REQUIRE_MUTATION_CONFIRMATION !== "false";
483
- const intentRouter = new IntentRouter({
484
- tools: toolRegistry,
485
- allowMutations: !isReadOnly,
486
- requireConfirmationForMutations: requireMutationConfirmation,
487
- });
488
- const readOnlyToolList = [
489
- listTableTool,
490
- listEnvironmentsTool,
491
- validateEnvironmentConfigTool,
492
- listScriptsTool,
493
- readDataTool,
494
- describeTableTool,
495
- searchSchemaTool,
496
- profileTableTool,
497
- relationshipInspectorTool,
498
- inspectDependenciesTool,
499
- testConnectionTool,
500
- explainQueryTool,
501
- ];
502
- const fullToolList = [
503
- insertDataTool,
504
- deleteDataTool,
505
- readDataTool,
506
- describeTableTool,
507
- updateDataTool,
508
- createTableTool,
509
- createIndexTool,
510
- dropTableTool,
511
- listTableTool,
512
- listDatabasesTool,
513
- listEnvironmentsTool,
514
- validateEnvironmentConfigTool,
515
- listScriptsTool,
516
- runScriptTool,
517
- searchSchemaTool,
518
- profileTableTool,
519
- relationshipInspectorTool,
520
- inspectDependenciesTool,
521
- testConnectionTool,
522
- explainQueryTool,
523
- ];
524
- const exposedTools = isReadOnly ? readOnlyToolList : fullToolList;
525
- // Request handlers
526
- // ... (rest of the code remains the same)
527
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
528
- tools: exposedTools,
529
- }));
530
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
531
- const { name, arguments: args } = request.params;
532
- try {
533
- let result;
534
- switch (name) {
535
- case insertDataTool.name:
536
- result = await insertDataTool.run(args);
537
- break;
538
- case deleteDataTool.name:
539
- result = await deleteDataTool.run(args);
540
- break;
541
- case readDataTool.name:
542
- result = await readDataTool.run(args);
543
- break;
544
- case updateDataTool.name:
545
- result = await updateDataTool.run(args);
546
- break;
547
- case createTableTool.name:
548
- result = await createTableTool.run(args);
549
- break;
550
- case createIndexTool.name:
551
- result = await createIndexTool.run(args);
552
- break;
553
- case listTableTool.name:
554
- result = await listTableTool.run(args);
555
- break;
556
- case listDatabasesTool.name:
557
- result = await listDatabasesTool.run(args);
558
- break;
559
- case listEnvironmentsTool.name:
560
- result = await listEnvironmentsTool.run(args);
561
- break;
562
- case validateEnvironmentConfigTool.name:
563
- result = await validateEnvironmentConfigTool.run(args);
564
- break;
565
- case listScriptsTool.name:
566
- result = await listScriptsTool.run(args);
567
- break;
568
- case runScriptTool.name:
569
- result = await runScriptTool.run(args);
570
- break;
571
- case inspectDependenciesTool.name:
572
- result = await inspectDependenciesTool.run(args);
573
- break;
574
- case dropTableTool.name:
575
- result = await dropTableTool.run(args);
576
- break;
577
- case testConnectionTool.name:
578
- result = await testConnectionTool.run(args);
579
- break;
580
- case explainQueryTool.name:
581
- result = await explainQueryTool.run(args);
582
- break;
583
- case describeTableTool.name:
584
- if (!args || typeof args.tableName !== "string") {
585
- return {
586
- content: [{ type: "text", text: `Missing or invalid 'tableName' argument for describe_table tool.` }],
587
- isError: true,
588
- };
589
- }
590
- result = await describeTableTool.run(args);
591
- break;
592
- case searchSchemaTool.name:
593
- result = await searchSchemaTool.run(args ?? {});
594
- break;
595
- case profileTableTool.name:
596
- if (!args || typeof args.tableName !== "string") {
597
- return {
598
- content: [{ type: "text", text: `Missing or invalid 'tableName' argument for profile_table tool.` }],
599
- isError: true,
600
- };
601
- }
602
- result = await profileTableTool.run(args);
603
- break;
604
- case relationshipInspectorTool.name:
605
- if (!args || typeof args.tableName !== "string") {
606
- return {
607
- content: [{ type: "text", text: `Missing or invalid 'tableName' argument for inspect_relationships tool.` }],
608
- isError: true,
609
- };
610
- }
611
- result = await relationshipInspectorTool.run(args);
612
- break;
613
- default:
614
- return {
615
- content: [{ type: "text", text: `Unknown tool: ${name}` }],
616
- isError: true,
617
- };
618
- }
619
- return {
620
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
621
- };
622
- }
623
- catch (error) {
624
- return {
625
- content: [{ type: "text", text: `Error occurred: ${error}` }],
626
- isError: true,
627
- };
628
- }
629
- });
630
- // Server startup
631
- async function runServer() {
632
- try {
633
- const transport = new StdioServerTransport();
634
- await server.connect(transport);
635
- }
636
- catch (error) {
637
- console.error("Fatal error running server:", error);
638
- process.exit(1);
639
- }
640
- }
641
- runServer().catch((error) => {
642
- console.error("Fatal error running server:", error);
5
+ version: "0.4.0",
6
+ tier: "admin",
7
+ }).catch((e) => {
8
+ console.error("Fatal:", e);
643
9
  process.exit(1);
644
10
  });
645
- // Tools that are exempt from requireApproval (read-only, no data modification)
646
- const APPROVAL_EXEMPT_TOOLS = new Set([
647
- "list_tables",
648
- "list_databases",
649
- "list_environments",
650
- "validate_environment_config",
651
- "list_scripts",
652
- "describe_table",
653
- "test_connection",
654
- "search_schema",
655
- "inspect_relationships",
656
- "inspect_dependencies",
657
- "read_data",
658
- "profile_table",
659
- "explain_query",
660
- ]);
661
- // Patch all tool handlers to ensure SQL connection, policy enforcement, and audit logging
662
- function wrapToolRun(tool) {
663
- const originalRun = tool.run.bind(tool);
664
- tool.run = async function (...args) {
665
- const startTime = Date.now();
666
- const rawArgs = (args[0] ?? {});
667
- const requestedEnvironment = typeof rawArgs.environment === "string" ? rawArgs.environment : undefined;
668
- const envConfig = environmentManager.getEnvironment(requestedEnvironment);
669
- // Build policy object from environment config
670
- const policy = {
671
- name: envConfig.name,
672
- readonly: envConfig.readonly ?? false,
673
- allowedTools: envConfig.allowedTools,
674
- deniedTools: envConfig.deniedTools,
675
- maxRowsDefault: envConfig.maxRowsDefault,
676
- requireApproval: envConfig.requireApproval ?? false,
677
- auditLevel: envConfig.auditLevel ?? "basic",
678
- };
679
- // Check denied tools policy (takes precedence)
680
- if (policy.deniedTools && policy.deniedTools.length > 0 && policy.deniedTools.includes(tool.name)) {
681
- return {
682
- success: false,
683
- message: `Tool '${tool.name}' is explicitly denied in environment '${policy.name}'.`,
684
- error: "TOOL_DENIED",
685
- };
686
- }
687
- // Check allowed tools policy
688
- if (policy.allowedTools && policy.allowedTools.length > 0 && !policy.allowedTools.includes(tool.name)) {
689
- return {
690
- success: false,
691
- message: `Tool '${tool.name}' is not permitted in environment '${policy.name}'. Allowed tools: ${policy.allowedTools.join(", ")}.`,
692
- error: "TOOL_NOT_ALLOWED",
693
- };
694
- }
695
- // Check readonly policy for mutating tools
696
- if (policy.readonly && MUTATING_TOOL_NAMES.has(tool.name)) {
697
- return {
698
- success: false,
699
- message: `Environment '${policy.name}' is read-only. Tool '${tool.name}' cannot be executed.`,
700
- error: "ENVIRONMENT_READONLY",
701
- };
702
- }
703
- // Check requireApproval policy (skip for metadata-only tools)
704
- if (policy.requireApproval && !APPROVAL_EXEMPT_TOOLS.has(tool.name)) {
705
- const hasConfirmation = rawArgs.confirm === true;
706
- if (!hasConfirmation) {
707
- return {
708
- success: false,
709
- requiresApproval: true,
710
- message: `Environment '${policy.name}' requires explicit approval for '${tool.name}'. Review the operation and re-run with confirm: true to proceed.`,
711
- error: "APPROVAL_REQUIRED",
712
- tool: tool.name,
713
- environment: policy.name,
714
- providedArguments: rawArgs,
715
- hint: "Add 'confirm: true' to your arguments after reviewing this operation.",
716
- };
717
- }
718
- }
719
- // Get connection for the specified or default environment
720
- const pool = await environmentManager.getConnection(policy.name);
721
- // Enrich args with environment info, policy, and connection pool
722
- const toolArgs = {
723
- ...rawArgs,
724
- environment: policy.name,
725
- environmentPolicy: policy,
726
- pool,
727
- };
728
- try {
729
- const result = await originalRun(toolArgs);
730
- const durationMs = Date.now() - startTime;
731
- // Audit log the successful invocation with environment-specific audit level
732
- auditLogger.logToolInvocation(tool.name, toolArgs, result, durationMs, {
733
- sessionId: SESSION_ID,
734
- environment: policy.name,
735
- auditLevel: policy.auditLevel,
736
- });
737
- return result;
738
- }
739
- catch (error) {
740
- const durationMs = Date.now() - startTime;
741
- // Audit log the failed invocation
742
- auditLogger.logToolInvocation(tool.name, toolArgs, { success: false, error: String(error) }, durationMs, {
743
- sessionId: SESSION_ID,
744
- environment: policy.name,
745
- auditLevel: policy.auditLevel,
746
- });
747
- throw error;
748
- }
749
- };
750
- }
751
- [insertDataTool, deleteDataTool, readDataTool, updateDataTool, createTableTool, createIndexTool, dropTableTool, listTableTool, listDatabasesTool, listEnvironmentsTool, validateEnvironmentConfigTool, listScriptsTool, runScriptTool, inspectDependenciesTool, describeTableTool, searchSchemaTool, profileTableTool, relationshipInspectorTool, testConnectionTool, explainQueryTool].forEach(wrapToolRun);
752
11
  //# sourceMappingURL=index.js.map