@eamonboyle/mssql-mcp 1.0.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.
Files changed (133) hide show
  1. package/README.md +153 -36
  2. package/dist/__tests__/ExplainQueryTool.test.d.ts +2 -0
  3. package/dist/__tests__/ExplainQueryTool.test.d.ts.map +1 -0
  4. package/dist/__tests__/ExplainQueryTool.test.js +96 -0
  5. package/dist/__tests__/ExplainQueryTool.test.js.map +1 -0
  6. package/dist/__tests__/config.test.d.ts +2 -0
  7. package/dist/__tests__/config.test.d.ts.map +1 -0
  8. package/dist/__tests__/config.test.js +29 -0
  9. package/dist/__tests__/config.test.js.map +1 -0
  10. package/dist/__tests__/db.test.d.ts +2 -0
  11. package/dist/__tests__/db.test.d.ts.map +1 -0
  12. package/dist/__tests__/db.test.js +204 -0
  13. package/dist/__tests__/db.test.js.map +1 -0
  14. package/dist/__tests__/promptRegistry.test.d.ts +2 -0
  15. package/dist/__tests__/promptRegistry.test.d.ts.map +1 -0
  16. package/dist/__tests__/promptRegistry.test.js +40 -0
  17. package/dist/__tests__/promptRegistry.test.js.map +1 -0
  18. package/dist/__tests__/resourceRegistry.test.d.ts +2 -0
  19. package/dist/__tests__/resourceRegistry.test.d.ts.map +1 -0
  20. package/dist/__tests__/resourceRegistry.test.js +40 -0
  21. package/dist/__tests__/resourceRegistry.test.js.map +1 -0
  22. package/dist/__tests__/schema.test.d.ts +2 -0
  23. package/dist/__tests__/schema.test.d.ts.map +1 -0
  24. package/dist/__tests__/schema.test.js +130 -0
  25. package/dist/__tests__/schema.test.js.map +1 -0
  26. package/dist/__tests__/sql.test.d.ts +2 -0
  27. package/dist/__tests__/sql.test.d.ts.map +1 -0
  28. package/dist/__tests__/sql.test.js +35 -0
  29. package/dist/__tests__/sql.test.js.map +1 -0
  30. package/dist/__tests__/toolRegistry.test.d.ts +2 -0
  31. package/dist/__tests__/toolRegistry.test.d.ts.map +1 -0
  32. package/dist/__tests__/toolRegistry.test.js +47 -0
  33. package/dist/__tests__/toolRegistry.test.js.map +1 -0
  34. package/dist/__tests__/validation.test.d.ts +2 -0
  35. package/dist/__tests__/validation.test.d.ts.map +1 -0
  36. package/dist/__tests__/validation.test.js +111 -0
  37. package/dist/__tests__/validation.test.js.map +1 -0
  38. package/dist/__tests__/writeTools.test.d.ts +2 -0
  39. package/dist/__tests__/writeTools.test.d.ts.map +1 -0
  40. package/dist/__tests__/writeTools.test.js +115 -0
  41. package/dist/__tests__/writeTools.test.js.map +1 -0
  42. package/dist/config.d.ts +5 -0
  43. package/dist/config.d.ts.map +1 -0
  44. package/dist/config.js +34 -0
  45. package/dist/config.js.map +1 -0
  46. package/dist/db.d.ts +28 -24
  47. package/dist/db.d.ts.map +1 -1
  48. package/dist/db.js +144 -89
  49. package/dist/db.js.map +1 -1
  50. package/dist/index.d.ts +2 -2
  51. package/dist/index.js +70 -105
  52. package/dist/index.js.map +1 -1
  53. package/dist/promptRegistry.d.ts +16 -0
  54. package/dist/promptRegistry.d.ts.map +1 -0
  55. package/dist/promptRegistry.js +107 -0
  56. package/dist/promptRegistry.js.map +1 -0
  57. package/dist/resourceRegistry.d.ts +12 -0
  58. package/dist/resourceRegistry.d.ts.map +1 -0
  59. package/dist/resourceRegistry.js +172 -0
  60. package/dist/resourceRegistry.js.map +1 -0
  61. package/dist/schema.d.ts +41 -0
  62. package/dist/schema.d.ts.map +1 -0
  63. package/dist/schema.js +211 -0
  64. package/dist/schema.js.map +1 -0
  65. package/dist/sql.d.ts +7 -0
  66. package/dist/sql.d.ts.map +1 -0
  67. package/dist/sql.js +73 -0
  68. package/dist/sql.js.map +1 -0
  69. package/dist/toolRegistry.d.ts +16 -0
  70. package/dist/toolRegistry.d.ts.map +1 -0
  71. package/dist/toolRegistry.js +401 -0
  72. package/dist/toolRegistry.js.map +1 -0
  73. package/dist/tools/CreateIndexTool.d.ts +30 -23
  74. package/dist/tools/CreateIndexTool.d.ts.map +1 -1
  75. package/dist/tools/CreateIndexTool.js +47 -71
  76. package/dist/tools/CreateIndexTool.js.map +1 -1
  77. package/dist/tools/CreateTableTool.d.ts +18 -11
  78. package/dist/tools/CreateTableTool.d.ts.map +1 -1
  79. package/dist/tools/CreateTableTool.js +37 -56
  80. package/dist/tools/CreateTableTool.js.map +1 -1
  81. package/dist/tools/DeleteDataTool.d.ts +22 -0
  82. package/dist/tools/DeleteDataTool.d.ts.map +1 -0
  83. package/dist/tools/DeleteDataTool.js +35 -0
  84. package/dist/tools/DeleteDataTool.js.map +1 -0
  85. package/dist/tools/DescribeObjectTool.d.ts +21 -0
  86. package/dist/tools/DescribeObjectTool.d.ts.map +1 -0
  87. package/dist/tools/DescribeObjectTool.js +31 -0
  88. package/dist/tools/DescribeObjectTool.js.map +1 -0
  89. package/dist/tools/DescribeTableTool.d.ts +19 -20
  90. package/dist/tools/DescribeTableTool.d.ts.map +1 -1
  91. package/dist/tools/DescribeTableTool.js +23 -41
  92. package/dist/tools/DescribeTableTool.js.map +1 -1
  93. package/dist/tools/DropTableTool.d.ts +13 -11
  94. package/dist/tools/DropTableTool.d.ts.map +1 -1
  95. package/dist/tools/DropTableTool.js +30 -44
  96. package/dist/tools/DropTableTool.js.map +1 -1
  97. package/dist/tools/ExplainQueryTool.d.ts +32 -0
  98. package/dist/tools/ExplainQueryTool.d.ts.map +1 -0
  99. package/dist/tools/ExplainQueryTool.js +102 -0
  100. package/dist/tools/ExplainQueryTool.js.map +1 -0
  101. package/dist/tools/InsertDataTool.d.ts +20 -16
  102. package/dist/tools/InsertDataTool.d.ts.map +1 -1
  103. package/dist/tools/InsertDataTool.js +91 -108
  104. package/dist/tools/InsertDataTool.js.map +1 -1
  105. package/dist/tools/ListObjectsTool.d.ts +20 -0
  106. package/dist/tools/ListObjectsTool.d.ts.map +1 -0
  107. package/dist/tools/ListObjectsTool.js +26 -0
  108. package/dist/tools/ListObjectsTool.js.map +1 -0
  109. package/dist/tools/ListTableTool.d.ts +20 -16
  110. package/dist/tools/ListTableTool.d.ts.map +1 -1
  111. package/dist/tools/ListTableTool.js +32 -49
  112. package/dist/tools/ListTableTool.js.map +1 -1
  113. package/dist/tools/ReadDataTool.d.ts +35 -41
  114. package/dist/tools/ReadDataTool.d.ts.map +1 -1
  115. package/dist/tools/ReadDataTool.js +92 -228
  116. package/dist/tools/ReadDataTool.js.map +1 -1
  117. package/dist/tools/SearchDataTool.d.ts +27 -0
  118. package/dist/tools/SearchDataTool.d.ts.map +1 -0
  119. package/dist/tools/SearchDataTool.js +61 -0
  120. package/dist/tools/SearchDataTool.js.map +1 -0
  121. package/dist/tools/UpdateDataTool.d.ts +21 -16
  122. package/dist/tools/UpdateDataTool.d.ts.map +1 -1
  123. package/dist/tools/UpdateDataTool.js +45 -65
  124. package/dist/tools/UpdateDataTool.js.map +1 -1
  125. package/dist/validation.d.ts +14 -0
  126. package/dist/validation.d.ts.map +1 -0
  127. package/dist/validation.js +134 -0
  128. package/dist/validation.js.map +1 -0
  129. package/dist/writeSafety.d.ts +21 -0
  130. package/dist/writeSafety.d.ts.map +1 -0
  131. package/dist/writeSafety.js +169 -0
  132. package/dist/writeSafety.js.map +1 -0
  133. package/package.json +17 -6
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptRegistry.js","sourceRoot":"","sources":["../src/promptRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export interface ResourceRegistryContext {
3
+ serverName: string;
4
+ serverVersion: string;
5
+ isReadOnly: boolean;
6
+ allowedDatabases: string[];
7
+ toolNames: string[];
8
+ maxRows: number;
9
+ queryTimeoutMs: number;
10
+ }
11
+ export declare function registerResources(server: McpServer, context: ResourceRegistryContext): void;
12
+ //# sourceMappingURL=resourceRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceRegistry.d.ts","sourceRoot":"","sources":["../src/resourceRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAqBtF,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AA0JD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,uBAAuB,GAC/B,IAAI,CAyGN"}
@@ -0,0 +1,172 @@
1
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { describeDatabaseObject, describeTableSchema, listDatabaseObjects, listDatabaseTables, } from "./schema.js";
3
+ import { promptDefinitions } from "./promptRegistry.js";
4
+ const resourceTemplates = [
5
+ {
6
+ name: "table_schema",
7
+ uriTemplate: "mssql://table/{databaseName}/{schemaName}/{tableName}",
8
+ description: "Detailed schema for a single table resource.",
9
+ mimeType: "application/json",
10
+ },
11
+ {
12
+ name: "object_definition",
13
+ uriTemplate: "mssql://object/{databaseName}/{schemaName}/{objectName}",
14
+ description: "Definition and metadata for a single table, view, procedure, function, or trigger.",
15
+ mimeType: "application/json",
16
+ },
17
+ ];
18
+ const RESOURCE_LIST_TTL_MS = 30000;
19
+ function buildResourceText(payload) {
20
+ return JSON.stringify(payload, null, 2);
21
+ }
22
+ function parseResourceUri(uri) {
23
+ const parsed = new URL(uri);
24
+ const segments = parsed.pathname
25
+ .split("/")
26
+ .filter(Boolean)
27
+ .map((segment) => decodeURIComponent(segment));
28
+ return {
29
+ resourceType: parsed.hostname,
30
+ segments,
31
+ };
32
+ }
33
+ function createListingCache(ttlMs) {
34
+ const cache = new Map();
35
+ return async function getCachedValue(key, loader) {
36
+ const now = Date.now();
37
+ const cached = cache.get(key);
38
+ if (cached && cached.expiresAt > now) {
39
+ return cached.value;
40
+ }
41
+ const value = await loader();
42
+ cache.set(key, {
43
+ value,
44
+ expiresAt: now + ttlMs,
45
+ });
46
+ return value;
47
+ };
48
+ }
49
+ async function readResourcePayload(uri, context, getCachedValue) {
50
+ const parsed = parseResourceUri(uri);
51
+ if (parsed.resourceType === "config") {
52
+ if (parsed.segments[0] === "server") {
53
+ return {
54
+ server: {
55
+ name: context.serverName,
56
+ version: context.serverVersion,
57
+ readOnly: context.isReadOnly,
58
+ allowedDatabases: context.allowedDatabases,
59
+ maxRows: context.maxRows,
60
+ queryTimeoutMs: context.queryTimeoutMs,
61
+ },
62
+ tools: context.toolNames,
63
+ };
64
+ }
65
+ if (parsed.segments[0] === "prompts") {
66
+ return {
67
+ prompts: promptDefinitions,
68
+ };
69
+ }
70
+ }
71
+ if (parsed.resourceType === "database") {
72
+ const [databaseName, resourceName] = parsed.segments;
73
+ if (resourceName === "tables") {
74
+ return {
75
+ databaseName,
76
+ tables: await getCachedValue(`tables:${databaseName}`, () => listDatabaseTables(databaseName)),
77
+ };
78
+ }
79
+ if (resourceName === "objects") {
80
+ return {
81
+ databaseName,
82
+ objects: await getCachedValue(`objects:${databaseName}`, () => listDatabaseObjects(databaseName)),
83
+ };
84
+ }
85
+ }
86
+ if (parsed.resourceType === "table") {
87
+ const [databaseName, schemaName, tableName] = parsed.segments;
88
+ return {
89
+ databaseName,
90
+ schemaName,
91
+ tableName,
92
+ columns: await describeTableSchema(tableName, databaseName, schemaName),
93
+ };
94
+ }
95
+ if (parsed.resourceType === "object") {
96
+ const [databaseName, schemaName, objectName] = parsed.segments;
97
+ const object = await describeDatabaseObject(objectName, databaseName, schemaName);
98
+ if (!object) {
99
+ throw new Error(`No object named '${objectName}' was found.`);
100
+ }
101
+ return object;
102
+ }
103
+ throw new Error(`Unknown resource URI: ${uri}`);
104
+ }
105
+ function buildReadHandler(context, getCachedValue) {
106
+ return async (uri) => ({
107
+ contents: [
108
+ {
109
+ uri: uri.href,
110
+ mimeType: "application/json",
111
+ text: buildResourceText(await readResourcePayload(uri.href, context, getCachedValue)),
112
+ },
113
+ ],
114
+ });
115
+ }
116
+ export function registerResources(server, context) {
117
+ const getCachedValue = createListingCache(RESOURCE_LIST_TTL_MS);
118
+ const readHandler = buildReadHandler(context, getCachedValue);
119
+ server.registerResource("server_config", "mssql://config/server", {
120
+ title: "Server Config",
121
+ description: "Server configuration, limits, and enabled tools.",
122
+ mimeType: "application/json",
123
+ }, readHandler);
124
+ server.registerResource("prompt_catalog", "mssql://config/prompts", {
125
+ title: "Prompt Catalog",
126
+ description: "Available prompt templates exposed by this server.",
127
+ mimeType: "application/json",
128
+ }, readHandler);
129
+ for (const databaseName of context.allowedDatabases) {
130
+ server.registerResource(`${databaseName}_tables`, `mssql://database/${encodeURIComponent(databaseName)}/tables`, {
131
+ title: `${databaseName} Tables`,
132
+ description: `Base tables available in database ${databaseName}.`,
133
+ mimeType: "application/json",
134
+ }, readHandler);
135
+ server.registerResource(`${databaseName}_objects`, `mssql://database/${encodeURIComponent(databaseName)}/objects`, {
136
+ title: `${databaseName} Objects`,
137
+ description: `Tables, views, procedures, functions, and triggers available in database ${databaseName}.`,
138
+ mimeType: "application/json",
139
+ }, readHandler);
140
+ }
141
+ server.registerResource("table_schema", new ResourceTemplate(resourceTemplates[0].uriTemplate, {
142
+ list: async () => ({
143
+ resources: (await Promise.all(context.allowedDatabases.map(async (databaseName) => {
144
+ const tables = await getCachedValue(`tables:${databaseName}`, () => listDatabaseTables(databaseName));
145
+ return tables.map((table) => ({
146
+ uri: `mssql://table/${encodeURIComponent(databaseName)}/${encodeURIComponent(table.schemaName)}/${encodeURIComponent(table.tableName)}`,
147
+ name: `${databaseName}.${table.schemaName}.${table.tableName}`,
148
+ }));
149
+ }))).flat(),
150
+ }),
151
+ }), {
152
+ title: "Table Schema",
153
+ description: resourceTemplates[0].description,
154
+ mimeType: resourceTemplates[0].mimeType,
155
+ }, readHandler);
156
+ server.registerResource("object_definition", new ResourceTemplate(resourceTemplates[1].uriTemplate, {
157
+ list: async () => ({
158
+ resources: (await Promise.all(context.allowedDatabases.map(async (databaseName) => {
159
+ const objects = await getCachedValue(`objects:${databaseName}`, () => listDatabaseObjects(databaseName));
160
+ return objects.map((object) => ({
161
+ uri: `mssql://object/${encodeURIComponent(databaseName)}/${encodeURIComponent(object.schemaName)}/${encodeURIComponent(object.name)}`,
162
+ name: `${databaseName}.${object.schemaName}.${object.name}`,
163
+ }));
164
+ }))).flat(),
165
+ }),
166
+ }), {
167
+ title: "Object Definition",
168
+ description: resourceTemplates[1].description,
169
+ mimeType: resourceTemplates[1].mimeType,
170
+ }, readHandler);
171
+ }
172
+ //# sourceMappingURL=resourceRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceRegistry.js","sourceRoot":"","sources":["../src/resourceRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import sql from "mssql";
2
+ export interface DatabaseObjectSummary {
3
+ name: string;
4
+ schemaName: string;
5
+ objectType: string;
6
+ typeCode: string;
7
+ typeDescription: string;
8
+ createdAt: Date;
9
+ modifiedAt: Date;
10
+ }
11
+ export interface DatabaseObjectDescription {
12
+ name: string;
13
+ schemaName: string;
14
+ objectType: string;
15
+ typeCode: string;
16
+ typeDescription: string;
17
+ createdAt: Date;
18
+ modifiedAt: Date;
19
+ definition?: string | null;
20
+ columns: Array<{
21
+ name: string;
22
+ dataType: string;
23
+ maxLength: number;
24
+ precision: number;
25
+ scale: number;
26
+ isNullable: boolean;
27
+ isIdentity: boolean;
28
+ defaultValue: string | null;
29
+ }>;
30
+ indexes: Array<{
31
+ name: string;
32
+ type: string;
33
+ isUnique: boolean;
34
+ columns: string[];
35
+ }>;
36
+ }
37
+ export declare function listDatabaseTables(databaseName?: string, schemaName?: string): Promise<sql.IRecordSet<any>>;
38
+ export declare function describeTableSchema(tableName: string, databaseName?: string, schemaName?: string): Promise<sql.IRecordSet<any>>;
39
+ export declare function listDatabaseObjects(databaseName?: string, objectTypes?: string[], schemaName?: string): Promise<DatabaseObjectSummary[]>;
40
+ export declare function describeDatabaseObject(objectName: string, databaseName?: string, schemaName?: string, objectTypes?: string[]): Promise<DatabaseObjectDescription | null>;
41
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;AAIxB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,EAAE,OAAO,CAAC;QACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;CACJ;AAED,wBAAsB,kBAAkB,CACtC,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,gCAuBpB;AAED,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,gCA8BpB;AAED,wBAAsB,mBAAmB,CACvC,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAwClC;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAoJ3C"}
package/dist/schema.js ADDED
@@ -0,0 +1,211 @@
1
+ import sql from "mssql";
2
+ import { getSqlRequest } from "./db.js";
3
+ import { getFriendlyObjectType, getObjectTypeCodes } from "./sql.js";
4
+ export async function listDatabaseTables(databaseName, schemaName) {
5
+ const { request, error } = await getSqlRequest(databaseName);
6
+ if (error) {
7
+ throw new Error(error);
8
+ }
9
+ if (schemaName) {
10
+ request.input("schemaName", sql.NVarChar, schemaName);
11
+ }
12
+ const schemaFilter = schemaName ? "AND TABLE_SCHEMA = @schemaName" : "";
13
+ const result = await request.query(`
14
+ SELECT
15
+ TABLE_SCHEMA AS schemaName,
16
+ TABLE_NAME AS tableName
17
+ FROM INFORMATION_SCHEMA.TABLES
18
+ WHERE TABLE_TYPE = 'BASE TABLE'
19
+ ${schemaFilter}
20
+ ORDER BY TABLE_SCHEMA, TABLE_NAME
21
+ `);
22
+ return result.recordset;
23
+ }
24
+ export async function describeTableSchema(tableName, databaseName, schemaName) {
25
+ const { request, error } = await getSqlRequest(databaseName);
26
+ if (error) {
27
+ throw new Error(error);
28
+ }
29
+ request.input("tableName", sql.NVarChar, tableName);
30
+ if (schemaName) {
31
+ request.input("schemaName", sql.NVarChar, schemaName);
32
+ }
33
+ const schemaFilter = schemaName ? "AND c.TABLE_SCHEMA = @schemaName" : "";
34
+ const result = await request.query(`
35
+ SELECT
36
+ c.TABLE_SCHEMA AS schemaName,
37
+ c.COLUMN_NAME AS name,
38
+ c.DATA_TYPE AS type,
39
+ c.IS_NULLABLE AS isNullable,
40
+ c.COLUMN_DEFAULT AS defaultValue,
41
+ c.CHARACTER_MAXIMUM_LENGTH AS maxLength,
42
+ c.NUMERIC_PRECISION AS numericPrecision,
43
+ c.NUMERIC_SCALE AS numericScale
44
+ FROM INFORMATION_SCHEMA.COLUMNS c
45
+ WHERE c.TABLE_NAME = @tableName
46
+ ${schemaFilter}
47
+ ORDER BY c.ORDINAL_POSITION
48
+ `);
49
+ return result.recordset;
50
+ }
51
+ export async function listDatabaseObjects(databaseName, objectTypes, schemaName) {
52
+ const { request, error } = await getSqlRequest(databaseName);
53
+ if (error) {
54
+ throw new Error(error);
55
+ }
56
+ const typeCodes = getObjectTypeCodes(objectTypes);
57
+ const typePlaceholders = typeCodes
58
+ .map((code, index) => {
59
+ const parameterName = `typeCode${index}`;
60
+ request.input(parameterName, sql.NVarChar, code);
61
+ return `@${parameterName}`;
62
+ })
63
+ .join(", ");
64
+ if (schemaName) {
65
+ request.input("schemaName", sql.NVarChar, schemaName);
66
+ }
67
+ const schemaFilter = schemaName ? "AND s.name = @schemaName" : "";
68
+ const result = await request.query(`
69
+ SELECT
70
+ o.name,
71
+ s.name AS schemaName,
72
+ o.type AS typeCode,
73
+ o.type_desc AS typeDescription,
74
+ o.create_date AS createdAt,
75
+ o.modify_date AS modifiedAt
76
+ FROM sys.objects o
77
+ INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
78
+ WHERE o.is_ms_shipped = 0
79
+ AND o.type IN (${typePlaceholders})
80
+ ${schemaFilter}
81
+ ORDER BY s.name, o.name
82
+ `);
83
+ return result.recordset.map((row) => ({
84
+ ...row,
85
+ objectType: getFriendlyObjectType(row.typeCode),
86
+ }));
87
+ }
88
+ export async function describeDatabaseObject(objectName, databaseName, schemaName, objectTypes) {
89
+ const { request, error } = await getSqlRequest(databaseName);
90
+ if (error) {
91
+ throw new Error(error);
92
+ }
93
+ request.input("objectName", sql.NVarChar, objectName);
94
+ if (schemaName) {
95
+ request.input("schemaName", sql.NVarChar, schemaName);
96
+ }
97
+ let typeFilter = "";
98
+ if (objectTypes && objectTypes.length > 0) {
99
+ const typeCodes = getObjectTypeCodes(objectTypes);
100
+ const typePlaceholders = typeCodes
101
+ .map((code, index) => {
102
+ const parameterName = `describeTypeCode${index}`;
103
+ request.input(parameterName, sql.NVarChar, code);
104
+ return `@${parameterName}`;
105
+ })
106
+ .join(", ");
107
+ typeFilter = `AND o.type IN (${typePlaceholders})`;
108
+ }
109
+ const schemaFilter = schemaName ? "AND s.name = @schemaName" : "";
110
+ const objectResult = await request.query(`
111
+ SELECT TOP (2)
112
+ o.object_id AS objectId,
113
+ o.name,
114
+ s.name AS schemaName,
115
+ o.type AS typeCode,
116
+ o.type_desc AS typeDescription,
117
+ o.create_date AS createdAt,
118
+ o.modify_date AS modifiedAt,
119
+ sm.definition
120
+ FROM sys.objects o
121
+ INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
122
+ LEFT JOIN sys.sql_modules sm ON sm.object_id = o.object_id
123
+ WHERE o.is_ms_shipped = 0
124
+ AND o.name = @objectName
125
+ ${schemaFilter}
126
+ ${typeFilter}
127
+ ORDER BY s.name, o.type, o.name
128
+ `);
129
+ const objectRows = objectResult.recordset;
130
+ if (objectRows.length > 1) {
131
+ const matches = objectRows
132
+ .map((row) => `${row.schemaName}.${row.name} (${getFriendlyObjectType(row.typeCode)})`)
133
+ .join(", ");
134
+ throw new Error(`Multiple objects named '${objectName}' matched the request. Specify schemaName or objectTypes to disambiguate. Matches: ${matches}.`);
135
+ }
136
+ const objectRow = objectRows[0];
137
+ if (!objectRow) {
138
+ return null;
139
+ }
140
+ request.input("objectId", sql.Int, objectRow.objectId);
141
+ const detailsResult = await request.query(`
142
+ SELECT
143
+ c.name,
144
+ t.name AS dataType,
145
+ c.max_length AS maxLength,
146
+ c.precision,
147
+ c.scale,
148
+ c.is_nullable AS isNullable,
149
+ c.is_identity AS isIdentity,
150
+ dc.definition AS defaultValue
151
+ FROM sys.columns c
152
+ INNER JOIN sys.types t ON t.user_type_id = c.user_type_id
153
+ LEFT JOIN sys.default_constraints dc
154
+ ON dc.parent_object_id = c.object_id
155
+ AND dc.parent_column_id = c.column_id
156
+ WHERE c.object_id = @objectId
157
+ ORDER BY c.column_id;
158
+
159
+ SELECT
160
+ i.name,
161
+ i.type_desc AS type,
162
+ i.is_unique AS isUnique,
163
+ c.name AS columnName,
164
+ ic.key_ordinal AS keyOrdinal
165
+ FROM sys.indexes i
166
+ INNER JOIN sys.index_columns ic
167
+ ON ic.object_id = i.object_id
168
+ AND ic.index_id = i.index_id
169
+ INNER JOIN sys.columns c
170
+ ON c.object_id = ic.object_id
171
+ AND c.column_id = ic.column_id
172
+ WHERE i.object_id = @objectId
173
+ AND i.is_hypothetical = 0
174
+ AND i.name IS NOT NULL
175
+ ORDER BY i.name, ic.key_ordinal
176
+ `);
177
+ const detailRecordsets = Array.isArray(detailsResult.recordsets)
178
+ ? detailsResult.recordsets
179
+ : [];
180
+ const columnsRecordset = (Array.isArray(detailRecordsets[0])
181
+ ? detailRecordsets[0]
182
+ : []);
183
+ const indexesRecordset = (Array.isArray(detailRecordsets[1])
184
+ ? detailRecordsets[1]
185
+ : []);
186
+ const indexes = new Map();
187
+ for (const row of indexesRecordset) {
188
+ if (!indexes.has(row.name)) {
189
+ indexes.set(row.name, {
190
+ name: row.name,
191
+ type: row.type,
192
+ isUnique: row.isUnique,
193
+ columns: [],
194
+ });
195
+ }
196
+ indexes.get(row.name)?.columns.push(row.columnName);
197
+ }
198
+ return {
199
+ name: objectRow.name,
200
+ schemaName: objectRow.schemaName,
201
+ objectType: getFriendlyObjectType(objectRow.typeCode),
202
+ typeCode: objectRow.typeCode,
203
+ typeDescription: objectRow.typeDescription,
204
+ createdAt: objectRow.createdAt,
205
+ modifiedAt: objectRow.modifiedAt,
206
+ definition: objectRow.definition,
207
+ columns: columnsRecordset,
208
+ indexes: [...indexes.values()],
209
+ };
210
+ }
211
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/sql.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare function isSafeSqlIdentifier(value: string): boolean;
2
+ export declare function assertSafeSqlIdentifier(value: string, label?: string): void;
3
+ export declare function quoteIdentifier(value: string): string;
4
+ export declare function buildQualifiedName(objectName: string, schemaName?: string): string;
5
+ export declare function getFriendlyObjectType(typeCode: string): string;
6
+ export declare function getObjectTypeCodes(objectTypes?: string[]): string[];
7
+ //# sourceMappingURL=sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAWA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAM1D;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,KAAK,SAAe,GACnB,IAAI,CAIN;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAQR;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmB9D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA0BnE"}