@eamonboyle/mssql-mcp 1.1.0 → 1.2.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 +134 -22
- package/dist/__tests__/ExplainQueryTool.test.d.ts +2 -0
- package/dist/__tests__/ExplainQueryTool.test.d.ts.map +1 -0
- package/dist/__tests__/ExplainQueryTool.test.js +96 -0
- package/dist/__tests__/ExplainQueryTool.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +29 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/db.test.d.ts +1 -1
- package/dist/__tests__/db.test.js +203 -203
- package/dist/__tests__/promptRegistry.test.d.ts +2 -0
- package/dist/__tests__/promptRegistry.test.d.ts.map +1 -0
- package/dist/__tests__/promptRegistry.test.js +40 -0
- package/dist/__tests__/promptRegistry.test.js.map +1 -0
- package/dist/__tests__/resourceRegistry.test.d.ts +2 -0
- package/dist/__tests__/resourceRegistry.test.d.ts.map +1 -0
- package/dist/__tests__/resourceRegistry.test.js +40 -0
- package/dist/__tests__/resourceRegistry.test.js.map +1 -0
- package/dist/__tests__/schema.test.d.ts +2 -0
- package/dist/__tests__/schema.test.d.ts.map +1 -0
- package/dist/__tests__/schema.test.js +130 -0
- package/dist/__tests__/schema.test.js.map +1 -0
- package/dist/__tests__/sql.test.d.ts +2 -0
- package/dist/__tests__/sql.test.d.ts.map +1 -0
- package/dist/__tests__/sql.test.js +35 -0
- package/dist/__tests__/sql.test.js.map +1 -0
- package/dist/__tests__/toolRegistry.test.d.ts +2 -0
- package/dist/__tests__/toolRegistry.test.d.ts.map +1 -0
- package/dist/__tests__/toolRegistry.test.js +47 -0
- package/dist/__tests__/toolRegistry.test.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +1 -1
- package/dist/__tests__/validation.test.js +110 -110
- package/dist/__tests__/validation.test.js.map +1 -1
- package/dist/__tests__/writeTools.test.d.ts +2 -0
- package/dist/__tests__/writeTools.test.d.ts.map +1 -0
- package/dist/__tests__/writeTools.test.js +115 -0
- package/dist/__tests__/writeTools.test.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +34 -0
- package/dist/config.js.map +1 -0
- package/dist/db.d.ts +28 -24
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +144 -112
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +70 -122
- package/dist/index.js.map +1 -1
- package/dist/promptRegistry.d.ts +16 -0
- package/dist/promptRegistry.d.ts.map +1 -0
- package/dist/promptRegistry.js +107 -0
- package/dist/promptRegistry.js.map +1 -0
- package/dist/resourceRegistry.d.ts +12 -0
- package/dist/resourceRegistry.d.ts.map +1 -0
- package/dist/resourceRegistry.js +172 -0
- package/dist/resourceRegistry.js.map +1 -0
- package/dist/schema.d.ts +41 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +211 -0
- package/dist/schema.js.map +1 -0
- package/dist/sql.d.ts +7 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +73 -0
- package/dist/sql.js.map +1 -0
- package/dist/toolRegistry.d.ts +16 -0
- package/dist/toolRegistry.d.ts.map +1 -0
- package/dist/toolRegistry.js +401 -0
- package/dist/toolRegistry.js.map +1 -0
- package/dist/tools/CreateIndexTool.d.ts +30 -23
- package/dist/tools/CreateIndexTool.d.ts.map +1 -1
- package/dist/tools/CreateIndexTool.js +47 -77
- package/dist/tools/CreateIndexTool.js.map +1 -1
- package/dist/tools/CreateTableTool.d.ts +18 -11
- package/dist/tools/CreateTableTool.d.ts.map +1 -1
- package/dist/tools/CreateTableTool.js +37 -61
- package/dist/tools/CreateTableTool.js.map +1 -1
- package/dist/tools/DeleteDataTool.d.ts +22 -0
- package/dist/tools/DeleteDataTool.d.ts.map +1 -0
- package/dist/tools/DeleteDataTool.js +35 -0
- package/dist/tools/DeleteDataTool.js.map +1 -0
- package/dist/tools/DescribeObjectTool.d.ts +21 -0
- package/dist/tools/DescribeObjectTool.d.ts.map +1 -0
- package/dist/tools/DescribeObjectTool.js +31 -0
- package/dist/tools/DescribeObjectTool.js.map +1 -0
- package/dist/tools/DescribeTableTool.d.ts +19 -20
- package/dist/tools/DescribeTableTool.d.ts.map +1 -1
- package/dist/tools/DescribeTableTool.js +23 -44
- package/dist/tools/DescribeTableTool.js.map +1 -1
- package/dist/tools/DropTableTool.d.ts +13 -11
- package/dist/tools/DropTableTool.d.ts.map +1 -1
- package/dist/tools/DropTableTool.js +30 -44
- package/dist/tools/DropTableTool.js.map +1 -1
- package/dist/tools/ExplainQueryTool.d.ts +32 -0
- package/dist/tools/ExplainQueryTool.d.ts.map +1 -0
- package/dist/tools/ExplainQueryTool.js +102 -0
- package/dist/tools/ExplainQueryTool.js.map +1 -0
- package/dist/tools/InsertDataTool.d.ts +20 -16
- package/dist/tools/InsertDataTool.d.ts.map +1 -1
- package/dist/tools/InsertDataTool.js +91 -108
- package/dist/tools/InsertDataTool.js.map +1 -1
- package/dist/tools/ListObjectsTool.d.ts +20 -0
- package/dist/tools/ListObjectsTool.d.ts.map +1 -0
- package/dist/tools/ListObjectsTool.js +26 -0
- package/dist/tools/ListObjectsTool.js.map +1 -0
- package/dist/tools/ListTableTool.d.ts +20 -16
- package/dist/tools/ListTableTool.d.ts.map +1 -1
- package/dist/tools/ListTableTool.js +32 -51
- package/dist/tools/ListTableTool.js.map +1 -1
- package/dist/tools/ReadDataTool.d.ts +35 -33
- package/dist/tools/ReadDataTool.d.ts.map +1 -1
- package/dist/tools/ReadDataTool.js +92 -105
- package/dist/tools/ReadDataTool.js.map +1 -1
- package/dist/tools/SearchDataTool.d.ts +27 -0
- package/dist/tools/SearchDataTool.d.ts.map +1 -0
- package/dist/tools/SearchDataTool.js +61 -0
- package/dist/tools/SearchDataTool.js.map +1 -0
- package/dist/tools/UpdateDataTool.d.ts +21 -16
- package/dist/tools/UpdateDataTool.d.ts.map +1 -1
- package/dist/tools/UpdateDataTool.js +45 -65
- package/dist/tools/UpdateDataTool.js.map +1 -1
- package/dist/validation.d.ts +13 -13
- package/dist/validation.js +133 -133
- package/dist/validation.js.map +1 -1
- package/dist/writeSafety.d.ts +21 -0
- package/dist/writeSafety.d.ts.map +1 -0
- package/dist/writeSafety.js +169 -0
- package/dist/writeSafety.js.map +1 -0
- package/package.json +5 -4
package/dist/db.js
CHANGED
|
@@ -1,113 +1,145 @@
|
|
|
1
|
-
import sql from "mssql";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
sqlPools.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
import sql from "mssql";
|
|
2
|
+
import { getQueryTimeoutMs } from "./config.js";
|
|
3
|
+
// Connection pools keyed by database name
|
|
4
|
+
const sqlPools = new Map();
|
|
5
|
+
function parseDatabaseList(value) {
|
|
6
|
+
if (!value || !value.trim()) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return value
|
|
10
|
+
.split(",")
|
|
11
|
+
.map((db) => db.trim())
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
}
|
|
14
|
+
function getDefaultDatabaseName() {
|
|
15
|
+
const allowedDatabases = parseDatabaseList(process.env.DATABASES);
|
|
16
|
+
const explicitDefault = process.env.DATABASE_NAME?.trim();
|
|
17
|
+
if (allowedDatabases.length === 0) {
|
|
18
|
+
return explicitDefault ?? null;
|
|
19
|
+
}
|
|
20
|
+
if (explicitDefault && allowedDatabases.includes(explicitDefault)) {
|
|
21
|
+
return explicitDefault;
|
|
22
|
+
}
|
|
23
|
+
return allowedDatabases[0] ?? null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the list of allowed database names.
|
|
27
|
+
* If DATABASES is set, returns those; otherwise returns only DATABASE_NAME.
|
|
28
|
+
*/
|
|
29
|
+
export function getAllowedDatabases() {
|
|
30
|
+
const allowedDatabases = parseDatabaseList(process.env.DATABASES);
|
|
31
|
+
if (allowedDatabases.length > 0) {
|
|
32
|
+
return allowedDatabases;
|
|
33
|
+
}
|
|
34
|
+
const defaultDb = process.env.DATABASE_NAME?.trim();
|
|
35
|
+
return defaultDb ? [defaultDb] : [];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the database name to use (param or default).
|
|
39
|
+
* Returns null if invalid.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveDatabaseName(databaseName) {
|
|
42
|
+
const resolved = databaseName?.trim() || getDefaultDatabaseName();
|
|
43
|
+
if (!resolved)
|
|
44
|
+
return null;
|
|
45
|
+
const allowed = getAllowedDatabases();
|
|
46
|
+
if (allowed.length === 0)
|
|
47
|
+
return null;
|
|
48
|
+
if (allowed.includes(resolved))
|
|
49
|
+
return resolved;
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function createSqlConfigForDatabase(databaseName) {
|
|
53
|
+
const trustServerCertificate = process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === "true";
|
|
54
|
+
const connectionTimeout = process.env.CONNECTION_TIMEOUT
|
|
55
|
+
? parseInt(process.env.CONNECTION_TIMEOUT, 10)
|
|
56
|
+
: 30;
|
|
57
|
+
return {
|
|
58
|
+
server: process.env.SERVER_NAME || "localhost",
|
|
59
|
+
database: databaseName,
|
|
60
|
+
user: process.env.DB_USER,
|
|
61
|
+
password: process.env.DB_PASSWORD,
|
|
62
|
+
requestTimeout: getQueryTimeoutMs(),
|
|
63
|
+
options: {
|
|
64
|
+
encrypt: false,
|
|
65
|
+
trustServerCertificate: trustServerCertificate || true,
|
|
66
|
+
enableArithAbort: true,
|
|
67
|
+
useUTC: false,
|
|
68
|
+
},
|
|
69
|
+
connectionTimeout: connectionTimeout * 1000,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function resolveConfiguredDatabase(databaseName) {
|
|
73
|
+
const resolved = resolveDatabaseName(databaseName);
|
|
74
|
+
if (!resolved) {
|
|
75
|
+
const allowed = getAllowedDatabases();
|
|
76
|
+
const configurationHint = allowed.length > 0
|
|
77
|
+
? `Allowed: ${allowed.join(", ")}.`
|
|
78
|
+
: "Set DATABASE_NAME or DATABASES to configure database access.";
|
|
79
|
+
return {
|
|
80
|
+
databaseName: "",
|
|
81
|
+
error: `Invalid or disallowed database. ${configurationHint} Use the databaseName parameter to target a specific configured database.`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return { databaseName: resolved };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Ensures a connection pool exists for the given database.
|
|
88
|
+
*/
|
|
89
|
+
export async function ensureSqlConnection(databaseName) {
|
|
90
|
+
const existing = sqlPools.get(databaseName);
|
|
91
|
+
if (existing && existing.connected) {
|
|
92
|
+
return existing;
|
|
93
|
+
}
|
|
94
|
+
if (existing) {
|
|
95
|
+
try {
|
|
96
|
+
await existing.close();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Ignore close errors
|
|
100
|
+
}
|
|
101
|
+
sqlPools.delete(databaseName);
|
|
102
|
+
}
|
|
103
|
+
const config = createSqlConfigForDatabase(databaseName);
|
|
104
|
+
const pool = new sql.ConnectionPool(config);
|
|
105
|
+
await pool.connect();
|
|
106
|
+
sqlPools.set(databaseName, pool);
|
|
107
|
+
return pool;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns a sql.Request for the given database.
|
|
111
|
+
* Resolves database name (param or default), validates against allowed list,
|
|
112
|
+
* ensures connection, and returns pool.request().
|
|
113
|
+
*/
|
|
114
|
+
export async function getSqlRequest(databaseName) {
|
|
115
|
+
const resolved = await resolveConfiguredDatabase(databaseName);
|
|
116
|
+
if (resolved.error) {
|
|
117
|
+
return {
|
|
118
|
+
request: null,
|
|
119
|
+
error: resolved.error,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const pool = await ensureSqlConnection(resolved.databaseName);
|
|
123
|
+
return { request: pool.request() };
|
|
124
|
+
}
|
|
125
|
+
export async function getDedicatedSqlPool(databaseName) {
|
|
126
|
+
const resolved = await resolveConfiguredDatabase(databaseName);
|
|
127
|
+
if (resolved.error) {
|
|
128
|
+
return {
|
|
129
|
+
pool: null,
|
|
130
|
+
error: resolved.error,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const config = {
|
|
134
|
+
...createSqlConfigForDatabase(resolved.databaseName),
|
|
135
|
+
pool: {
|
|
136
|
+
max: 1,
|
|
137
|
+
min: 0,
|
|
138
|
+
idleTimeoutMillis: 30000,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const pool = new sql.ConnectionPool(config);
|
|
142
|
+
await pool.connect();
|
|
143
|
+
return { pool };
|
|
144
|
+
}
|
|
113
145
|
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,0CAA0C;AAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8B,CAAC;AAEvD,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,sBAAsB;IAC7B,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IAE1D,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,eAAe,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,IAAI,eAAe,IAAI,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAClE,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,gBAAgB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClE,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IACpD,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAqB;IACvD,MAAM,QAAQ,GAAG,YAAY,EAAE,IAAI,EAAE,IAAI,sBAAsB,EAAE,CAAC;IAClE,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAChD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,YAAoB;IACtD,MAAM,sBAAsB,GAC1B,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC;IACjE,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB;QACtD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAC9C,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,WAAW;QAC9C,QAAQ,EAAE,YAAY;QACtB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO;QACzB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;QACjC,cAAc,EAAE,iBAAiB,EAAE;QACnC,OAAO,EAAE;YACP,OAAO,EAAE,KAAK;YACd,sBAAsB,EAAE,sBAAsB,IAAI,IAAI;YACtD,gBAAgB,EAAE,IAAI;YACtB,MAAM,EAAE,KAAK;SACd;QACD,iBAAiB,EAAE,iBAAiB,GAAG,IAAI;KAC9B,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,YAAqB;IAErB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;QACtC,MAAM,iBAAiB,GACrB,OAAO,CAAC,MAAM,GAAG,CAAC;YAChB,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACnC,CAAC,CAAC,8DAA8D,CAAC;QAErE,OAAO;YACL,YAAY,EAAE,EAAE;YAChB,KAAK,EAAE,mCAAmC,iBAAiB,2EAA2E;SACvI,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAoB;IAEpB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QACD,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,MAAM,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,YAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAAC,YAAY,CAAC,CAAC;IAC/D,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO;YACL,OAAO,EAAE,IAA8B;YACvC,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAAC,YAAY,CAAC,CAAC;IAC/D,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO;YACL,IAAI,EAAE,IAAqC;YAC3C,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG;QACb,GAAG,0BAA0B,CAAC,QAAQ,CAAC,YAAY,CAAC;QACpD,IAAI,EAAE;YACJ,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,CAAC;YACN,iBAAiB,EAAE,KAAK;SACzB;KACY,CAAC;IAEhB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACrB,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
export {};
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export {};
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,123 +1,71 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
result = await listTableTool.run(args);
|
|
72
|
-
break;
|
|
73
|
-
case dropTableTool.name:
|
|
74
|
-
result = await dropTableTool.run(args);
|
|
75
|
-
break;
|
|
76
|
-
case describeTableTool.name:
|
|
77
|
-
if (!args || typeof args.tableName !== "string") {
|
|
78
|
-
return {
|
|
79
|
-
content: [
|
|
80
|
-
{
|
|
81
|
-
type: "text",
|
|
82
|
-
text: `Missing or invalid 'tableName' argument for describe_table tool.`,
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
isError: true,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
result = await describeTableTool.run(args);
|
|
89
|
-
break;
|
|
90
|
-
default:
|
|
91
|
-
return {
|
|
92
|
-
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
93
|
-
isError: true,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
return {
|
|
102
|
-
content: [{ type: "text", text: `Error occurred: ${error}` }],
|
|
103
|
-
isError: true,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
// Server startup
|
|
108
|
-
async function runServer() {
|
|
109
|
-
try {
|
|
110
|
-
const transport = new StdioServerTransport();
|
|
111
|
-
await server.connect(transport);
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.error("Fatal error running server:", error);
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
runServer().catch((error) => {
|
|
119
|
-
console.error("Fatal error running server:", error);
|
|
120
|
-
process.exit(1);
|
|
121
|
-
});
|
|
122
|
-
// Tools call getSqlRequest(databaseName) internally - no wrapping needed
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as dotenv from "dotenv";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
dotenv.config();
|
|
6
|
+
import { getMaxRows, getQueryTimeoutMs } from "./config.js";
|
|
7
|
+
import { getAllowedDatabases } from "./db.js";
|
|
8
|
+
import { registerPrompts } from "./promptRegistry.js";
|
|
9
|
+
import { registerResources } from "./resourceRegistry.js";
|
|
10
|
+
import { getAvailableTools } from "./toolRegistry.js";
|
|
11
|
+
const SERVER_VERSION = "1.2.0";
|
|
12
|
+
const SERVER_NAME = "mssql-mcp-server";
|
|
13
|
+
const isReadOnly = process.env.READONLY === "true";
|
|
14
|
+
const allowedDatabases = getAllowedDatabases();
|
|
15
|
+
const availableTools = getAvailableTools(isReadOnly);
|
|
16
|
+
const baseInstructions = "Use list_objects or list_table to inspect schema before querying data. Prefer read_data, search_data, and explain_query for safe read-only analysis.";
|
|
17
|
+
const readOnlyInstructions = " This server is READONLY: write/DDL MCP tools are disabled. Never use sqlcmd, SSMS, other DB CLI tools, or terminal scripts to perform INSERT, UPDATE, DELETE, or DDL as a workaround—state that the user must set READONLY=false on this server or apply changes themselves.";
|
|
18
|
+
const server = new McpServer({
|
|
19
|
+
name: SERVER_NAME,
|
|
20
|
+
version: SERVER_VERSION,
|
|
21
|
+
}, {
|
|
22
|
+
instructions: isReadOnly
|
|
23
|
+
? baseInstructions + readOnlyInstructions
|
|
24
|
+
: baseInstructions,
|
|
25
|
+
});
|
|
26
|
+
function asTextToolResult(result) {
|
|
27
|
+
const isError = typeof result === "object" &&
|
|
28
|
+
result !== null &&
|
|
29
|
+
"success" in result &&
|
|
30
|
+
result.success === false;
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
33
|
+
isError,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function registerTools(serverInstance) {
|
|
37
|
+
for (const definition of availableTools) {
|
|
38
|
+
serverInstance.registerTool(definition.tool.name, {
|
|
39
|
+
title: definition.tool.name,
|
|
40
|
+
description: definition.tool.description,
|
|
41
|
+
inputSchema: definition.inputSchema,
|
|
42
|
+
annotations: definition.annotations,
|
|
43
|
+
}, async (args) => asTextToolResult(await definition.tool.run(args)));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
registerTools(server);
|
|
47
|
+
registerResources(server, {
|
|
48
|
+
serverName: SERVER_NAME,
|
|
49
|
+
serverVersion: SERVER_VERSION,
|
|
50
|
+
isReadOnly,
|
|
51
|
+
allowedDatabases,
|
|
52
|
+
toolNames: availableTools.map((tool) => tool.tool.name),
|
|
53
|
+
maxRows: getMaxRows(),
|
|
54
|
+
queryTimeoutMs: getQueryTimeoutMs(),
|
|
55
|
+
});
|
|
56
|
+
registerPrompts(server, { isReadOnly });
|
|
57
|
+
async function runServer() {
|
|
58
|
+
try {
|
|
59
|
+
const transport = new StdioServerTransport();
|
|
60
|
+
await server.connect(transport);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error("Fatal error running server:", error);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
runServer().catch((error) => {
|
|
68
|
+
console.error("Fatal error running server:", error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
123
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export interface PromptDefinition {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
arguments?: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
export declare const promptDefinitions: PromptDefinition[];
|
|
12
|
+
export interface RegisterPromptsOptions {
|
|
13
|
+
isReadOnly: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function registerPrompts(server: McpServer, options: RegisterPromptsOptions): void;
|
|
16
|
+
//# sourceMappingURL=promptRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promptRegistry.d.ts","sourceRoot":"","sources":["../src/promptRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,EAiD/C,CAAC;AAYF,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,OAAO,CAAC;CACrB;AAkDD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CA0BN"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const promptDefinitions = [
|
|
3
|
+
{
|
|
4
|
+
name: "explore_schema",
|
|
5
|
+
description: "Guide the assistant to inspect SQL Server schema before answering a database question.",
|
|
6
|
+
arguments: [
|
|
7
|
+
{
|
|
8
|
+
name: "goal",
|
|
9
|
+
description: "What you want to understand or build from the schema.",
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "databaseName",
|
|
14
|
+
description: "Configured database to inspect first.",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "draft_safe_select",
|
|
20
|
+
description: "Draft a safe read-only SQL workflow using schema inspection before running a SELECT.",
|
|
21
|
+
arguments: [
|
|
22
|
+
{
|
|
23
|
+
name: "question",
|
|
24
|
+
description: "Business question to answer with SQL.",
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "databaseName",
|
|
29
|
+
description: "Configured database to inspect first.",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "review_write_operation",
|
|
35
|
+
description: "Review a proposed INSERT, UPDATE, DELETE, or DDL change before execution. When the server is read-only, directs the assistant to stop and avoid terminal or external SQL clients.",
|
|
36
|
+
arguments: [
|
|
37
|
+
{
|
|
38
|
+
name: "operation",
|
|
39
|
+
description: "The change you want to make.",
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "databaseName",
|
|
44
|
+
description: "Configured database the change targets.",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
function buildPromptMessage(text) {
|
|
50
|
+
return {
|
|
51
|
+
role: "user",
|
|
52
|
+
content: {
|
|
53
|
+
type: "text",
|
|
54
|
+
text,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function createPromptMessageBuilders(isReadOnly) {
|
|
59
|
+
return {
|
|
60
|
+
explore_schema: (args) => ({
|
|
61
|
+
description: "Inspect the schema before answering or generating SQL.",
|
|
62
|
+
messages: [
|
|
63
|
+
buildPromptMessage(`Inspect the SQL Server schema before answering the request.\nGoal: ${args.goal ?? "Understand the database shape"}\nDatabase: ${args.databaseName ?? "default configured database"}\nUse list_objects or list_table first, then describe_object or describe_table before writing SQL.`),
|
|
64
|
+
],
|
|
65
|
+
}),
|
|
66
|
+
draft_safe_select: (args) => ({
|
|
67
|
+
description: "Draft a read-only SQL workflow that inspects schema before querying data.",
|
|
68
|
+
messages: [
|
|
69
|
+
buildPromptMessage(`Answer this database question safely: ${args.question ?? "No question provided"}\nDatabase: ${args.databaseName ?? "default configured database"}\nInspect relevant schema first, then use read_data or search_data. Keep the final SQL read-only and explain assumptions.`),
|
|
70
|
+
],
|
|
71
|
+
}),
|
|
72
|
+
review_write_operation: (args) => {
|
|
73
|
+
const operation = args.operation ?? "No operation provided";
|
|
74
|
+
const database = args.databaseName ?? "default configured database";
|
|
75
|
+
const body = isReadOnly
|
|
76
|
+
? `Review this proposed change: ${operation}\nDatabase: ${database}
|
|
77
|
+
|
|
78
|
+
This MCP SQL Server connection is read-only (confirm with resource mssql://config/server — readOnly should be true). Write tools such as delete_data, update_data, insert_data, and DDL tools are not available.
|
|
79
|
+
|
|
80
|
+
STOP: Do not execute this change through the assistant. Do not open a terminal or use sqlcmd, SSMS, Azure Data Studio, PowerShell SQL cmdlets, ODBC/JDBC one-off scripts, or any other database client to apply INSERT, UPDATE, DELETE, or DDL as a workaround. Tell the user their MCP server is read-only and they must turn off READONLY (or run the change themselves manually outside this assistant) if they want execution here.
|
|
81
|
+
|
|
82
|
+
You may still: outline risks, confirm keys and scope, and suggest read-only preview SELECTs for discussion only.`
|
|
83
|
+
: `Review this proposed change before execution: ${operation}\nDatabase: ${database}\nConfirm the target objects, verify WHERE clauses where applicable, and suggest preview queries before any write tool is used.`;
|
|
84
|
+
return {
|
|
85
|
+
description: "Review a proposed change and identify safety checks before running it.",
|
|
86
|
+
messages: [buildPromptMessage(body)],
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function registerPrompts(server, options) {
|
|
92
|
+
const promptMessageBuilders = createPromptMessageBuilders(options.isReadOnly);
|
|
93
|
+
for (const prompt of promptDefinitions) {
|
|
94
|
+
const argsShape = Object.fromEntries((prompt.arguments ?? []).map((argument) => [
|
|
95
|
+
argument.name,
|
|
96
|
+
argument.required
|
|
97
|
+
? z.string().describe(argument.description)
|
|
98
|
+
: z.string().describe(argument.description).optional(),
|
|
99
|
+
]));
|
|
100
|
+
server.registerPrompt(prompt.name, {
|
|
101
|
+
title: prompt.name,
|
|
102
|
+
description: prompt.description,
|
|
103
|
+
argsSchema: argsShape,
|
|
104
|
+
}, (args) => promptMessageBuilders[prompt.name](args));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=promptRegistry.js.map
|