@elad-nofy/mssql-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/dist/config.d.ts +36 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +32 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +88 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/mssqlClient.d.ts +17 -0
  12. package/dist/mssqlClient.d.ts.map +1 -0
  13. package/dist/mssqlClient.js +78 -0
  14. package/dist/mssqlClient.js.map +1 -0
  15. package/dist/tools/availability.d.ts +50 -0
  16. package/dist/tools/availability.d.ts.map +1 -0
  17. package/dist/tools/availability.js +153 -0
  18. package/dist/tools/availability.js.map +1 -0
  19. package/dist/tools/connection.d.ts +32 -0
  20. package/dist/tools/connection.d.ts.map +1 -0
  21. package/dist/tools/connection.js +63 -0
  22. package/dist/tools/connection.js.map +1 -0
  23. package/dist/tools/health.d.ts +89 -0
  24. package/dist/tools/health.d.ts.map +1 -0
  25. package/dist/tools/health.js +189 -0
  26. package/dist/tools/health.js.map +1 -0
  27. package/dist/tools/index.d.ts +7 -0
  28. package/dist/tools/index.d.ts.map +1 -0
  29. package/dist/tools/index.js +7 -0
  30. package/dist/tools/index.js.map +1 -0
  31. package/dist/tools/jobs.d.ts +53 -0
  32. package/dist/tools/jobs.d.ts.map +1 -0
  33. package/dist/tools/jobs.js +161 -0
  34. package/dist/tools/jobs.js.map +1 -0
  35. package/dist/tools/performance.d.ts +60 -0
  36. package/dist/tools/performance.d.ts.map +1 -0
  37. package/dist/tools/performance.js +162 -0
  38. package/dist/tools/performance.js.map +1 -0
  39. package/dist/tools/queries.d.ts +59 -0
  40. package/dist/tools/queries.d.ts.map +1 -0
  41. package/dist/tools/queries.js +125 -0
  42. package/dist/tools/queries.js.map +1 -0
  43. package/package.json +54 -0
@@ -0,0 +1,153 @@
1
+ import { z } from 'zod';
2
+ export const availabilityTools = {
3
+ get_ag_status: {
4
+ description: 'Get Always On Availability Group status and health',
5
+ inputSchema: z.object({}),
6
+ handler: async (client) => {
7
+ // First check if HADR is enabled
8
+ const hadrCheck = await client.query("SELECT CAST(SERVERPROPERTY('IsHadrEnabled') AS INT) as is_hadr_enabled");
9
+ if (!hadrCheck[0]?.is_hadr_enabled) {
10
+ return {
11
+ hadrEnabled: false,
12
+ message: 'Always On Availability Groups is not enabled on this server',
13
+ };
14
+ }
15
+ const query = `
16
+ SELECT
17
+ ag.name as ag_name,
18
+ ag.group_id,
19
+ ags.primary_replica,
20
+ ags.primary_recovery_health_desc as primary_health,
21
+ ags.secondary_recovery_health_desc as secondary_health,
22
+ ags.synchronization_health_desc as sync_health,
23
+ ar.replica_server_name,
24
+ ar.availability_mode_desc as availability_mode,
25
+ ar.failover_mode_desc as failover_mode,
26
+ ars.role_desc as current_role,
27
+ ars.operational_state_desc as operational_state,
28
+ ars.connected_state_desc as connected_state,
29
+ ars.recovery_health_desc as recovery_health,
30
+ ars.synchronization_health_desc as replica_sync_health,
31
+ ars.last_connect_error_number,
32
+ ars.last_connect_error_description
33
+ FROM sys.availability_groups ag
34
+ INNER JOIN sys.dm_hadr_availability_group_states ags ON ag.group_id = ags.group_id
35
+ INNER JOIN sys.availability_replicas ar ON ag.group_id = ar.group_id
36
+ INNER JOIN sys.dm_hadr_availability_replica_states ars ON ar.replica_id = ars.replica_id
37
+ ORDER BY ag.name, ar.replica_server_name
38
+ `;
39
+ const replicas = await client.query(query);
40
+ // Get database-level sync status
41
+ const dbQuery = `
42
+ SELECT
43
+ ag.name as ag_name,
44
+ adc.database_name,
45
+ drs.is_local,
46
+ drs.is_primary_replica,
47
+ drs.synchronization_state_desc as sync_state,
48
+ drs.synchronization_health_desc as sync_health,
49
+ drs.database_state_desc as db_state,
50
+ drs.is_suspended,
51
+ drs.suspend_reason_desc,
52
+ drs.log_send_queue_size,
53
+ drs.log_send_rate,
54
+ drs.redo_queue_size,
55
+ drs.redo_rate,
56
+ drs.last_commit_time,
57
+ DATEDIFF(SECOND, drs.last_commit_time, GETDATE()) as seconds_behind
58
+ FROM sys.availability_groups ag
59
+ INNER JOIN sys.availability_databases_cluster adc ON ag.group_id = adc.group_id
60
+ INNER JOIN sys.dm_hadr_database_replica_states drs ON adc.group_database_id = drs.group_database_id
61
+ ORDER BY ag.name, adc.database_name, drs.is_primary_replica DESC
62
+ `;
63
+ const databases = await client.query(dbQuery);
64
+ return {
65
+ hadrEnabled: true,
66
+ replicas,
67
+ databases,
68
+ };
69
+ },
70
+ },
71
+ get_replica_states: {
72
+ description: 'Get detailed state information for all availability group replicas',
73
+ inputSchema: z.object({
74
+ agName: z.string().optional().describe('Filter by availability group name'),
75
+ }),
76
+ handler: async (client, args) => {
77
+ const agFilter = args.agName ? `WHERE ag.name = '${args.agName}'` : '';
78
+ const query = `
79
+ SELECT
80
+ ag.name as ag_name,
81
+ ar.replica_server_name,
82
+ ars.role_desc as role,
83
+ ar.availability_mode_desc as availability_mode,
84
+ ar.failover_mode_desc as failover_mode,
85
+ ar.seeding_mode_desc as seeding_mode,
86
+ ars.operational_state_desc as operational_state,
87
+ ars.connected_state_desc as connected_state,
88
+ ars.recovery_health_desc as recovery_health,
89
+ ars.synchronization_health_desc as sync_health,
90
+ ar.endpoint_url,
91
+ ar.session_timeout,
92
+ ar.primary_role_allow_connections_desc as primary_connections,
93
+ ar.secondary_role_allow_connections_desc as secondary_connections,
94
+ ar.backup_priority,
95
+ ar.read_only_routing_url
96
+ FROM sys.availability_groups ag
97
+ INNER JOIN sys.availability_replicas ar ON ag.group_id = ar.group_id
98
+ INNER JOIN sys.dm_hadr_availability_replica_states ars ON ar.replica_id = ars.replica_id
99
+ ${agFilter}
100
+ ORDER BY ag.name, ars.role_desc, ar.replica_server_name
101
+ `;
102
+ return await client.query(query);
103
+ },
104
+ },
105
+ get_cluster_status: {
106
+ description: 'Get Windows Server Failover Cluster status for the SQL Server instance',
107
+ inputSchema: z.object({}),
108
+ handler: async (client) => {
109
+ // Check if this is a clustered instance
110
+ const clusterCheck = await client.query("SELECT CAST(SERVERPROPERTY('IsClustered') AS INT) as is_clustered");
111
+ if (!clusterCheck[0]?.is_clustered) {
112
+ return {
113
+ isClustered: false,
114
+ message: 'This SQL Server instance is not clustered',
115
+ };
116
+ }
117
+ const query = `
118
+ SELECT
119
+ cluster_name,
120
+ quorum_type_desc as quorum_type,
121
+ quorum_state_desc as quorum_state
122
+ FROM sys.dm_hadr_cluster
123
+ `;
124
+ const cluster = await client.query(query);
125
+ const membersQuery = `
126
+ SELECT
127
+ member_name,
128
+ member_type_desc as member_type,
129
+ member_state_desc as member_state,
130
+ number_of_quorum_votes
131
+ FROM sys.dm_hadr_cluster_members
132
+ `;
133
+ const members = await client.query(membersQuery);
134
+ const networksQuery = `
135
+ SELECT
136
+ network_subnet_ip,
137
+ network_subnet_ipv4_mask,
138
+ network_subnet_prefix_length,
139
+ is_public,
140
+ is_ipv4
141
+ FROM sys.dm_hadr_cluster_networks
142
+ `;
143
+ const networks = await client.query(networksQuery);
144
+ return {
145
+ isClustered: true,
146
+ cluster: cluster[0],
147
+ members,
148
+ networks,
149
+ };
150
+ },
151
+ },
152
+ };
153
+ //# sourceMappingURL=availability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability.js","sourceRoot":"","sources":["../../src/tools/availability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,aAAa,EAAE;QACb,WAAW,EAAE,oDAAoD;QACjE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,iCAAiC;YACjC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,KAAK,CAClC,wEAAwE,CACzE,CAAC;YAEF,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;gBACnC,OAAO;oBACL,WAAW,EAAE,KAAK;oBAClB,OAAO,EAAE,6DAA6D;iBACvE,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;OAuBb,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAE3C,iCAAiC;YACjC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;OAqBf,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE9C,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,QAAQ;gBACR,SAAS;aACV,CAAC;QACJ,CAAC;KACF;IAED,kBAAkB,EAAE;QAClB,WAAW,EAAE,oEAAoE;QACjF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;SAC5E,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAAyB,EAAE,EAAE;YAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAEvE,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;UAqBV,QAAQ;;OAEX,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,kBAAkB,EAAE;QAClB,WAAW,EAAE,wEAAwE;QACrF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,wCAAwC;YACxC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,KAAK,CACrC,mEAAmE,CACpE,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;gBACnC,OAAO;oBACL,WAAW,EAAE,KAAK;oBAClB,OAAO,EAAE,2CAA2C;iBACrD,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG;;;;;;OAMb,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAE1C,MAAM,YAAY,GAAG;;;;;;;OAOpB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAEjD,MAAM,aAAa,GAAG;;;;;;;;OAQrB,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAEnD,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;gBACnB,OAAO;gBACP,QAAQ;aACT,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ import { MssqlClient } from '../mssqlClient.js';
3
+ export declare const connectionTools: {
4
+ test_connection: {
5
+ description: string;
6
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
7
+ handler: (client: MssqlClient) => Promise<{
8
+ success: boolean;
9
+ version?: string;
10
+ error?: string;
11
+ }>;
12
+ };
13
+ list_databases: {
14
+ description: string;
15
+ inputSchema: z.ZodObject<{
16
+ includeSystem: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ includeSystem: boolean;
19
+ }, {
20
+ includeSystem?: boolean | undefined;
21
+ }>;
22
+ handler: (client: MssqlClient, args: {
23
+ includeSystem?: boolean;
24
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
25
+ };
26
+ get_server_info: {
27
+ description: string;
28
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
29
+ handler: (client: MssqlClient) => Promise<import("mssql").IRecordSet<unknown>>;
30
+ };
31
+ };
32
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/tools/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,eAAO,MAAM,eAAe;;;;0BAIA,WAAW;;;;;;;;;;;;;;;0BAWX,WAAW,QAAQ;YAAE,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE;;;;;0BA8B9C,WAAW;;CAoBtC,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { z } from 'zod';
2
+ export const connectionTools = {
3
+ test_connection: {
4
+ description: 'Test the connection to SQL Server and verify authentication',
5
+ inputSchema: z.object({}),
6
+ handler: async (client) => {
7
+ const result = await client.testConnection();
8
+ return result;
9
+ },
10
+ },
11
+ list_databases: {
12
+ description: 'List all databases on the SQL Server instance with their status and size',
13
+ inputSchema: z.object({
14
+ includeSystem: z.boolean().optional().default(false).describe('Include system databases (master, model, msdb, tempdb)'),
15
+ }),
16
+ handler: async (client, args) => {
17
+ const systemFilter = args.includeSystem
18
+ ? ''
19
+ : "WHERE d.name NOT IN ('master', 'model', 'msdb', 'tempdb')";
20
+ const query = `
21
+ SELECT
22
+ d.name,
23
+ d.database_id,
24
+ d.state_desc as state,
25
+ d.recovery_model_desc as recovery_model,
26
+ d.compatibility_level,
27
+ d.collation_name,
28
+ d.create_date,
29
+ CAST(SUM(mf.size) * 8.0 / 1024 AS DECIMAL(10,2)) as size_mb
30
+ FROM sys.databases d
31
+ LEFT JOIN sys.master_files mf ON d.database_id = mf.database_id
32
+ ${systemFilter}
33
+ GROUP BY d.name, d.database_id, d.state_desc, d.recovery_model_desc,
34
+ d.compatibility_level, d.collation_name, d.create_date
35
+ ORDER BY d.name
36
+ `;
37
+ return await client.query(query);
38
+ },
39
+ },
40
+ get_server_info: {
41
+ description: 'Get SQL Server instance information including version, edition, and configuration',
42
+ inputSchema: z.object({}),
43
+ handler: async (client) => {
44
+ const query = `
45
+ SELECT
46
+ SERVERPROPERTY('ServerName') as server_name,
47
+ SERVERPROPERTY('InstanceName') as instance_name,
48
+ SERVERPROPERTY('ProductVersion') as version,
49
+ SERVERPROPERTY('ProductLevel') as product_level,
50
+ SERVERPROPERTY('Edition') as edition,
51
+ SERVERPROPERTY('EngineEdition') as engine_edition,
52
+ SERVERPROPERTY('Collation') as collation,
53
+ SERVERPROPERTY('IsHadrEnabled') as is_hadr_enabled,
54
+ SERVERPROPERTY('IsClustered') as is_clustered,
55
+ @@MAX_CONNECTIONS as max_connections,
56
+ (SELECT COUNT(*) FROM sys.dm_exec_connections) as current_connections
57
+ `;
58
+ const result = await client.query(query);
59
+ return result[0];
60
+ },
61
+ },
62
+ };
63
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/tools/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,eAAe,EAAE;QACf,WAAW,EAAE,6DAA6D;QAC1E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;YAC7C,OAAO,MAAM,CAAC;QAChB,CAAC;KACF;IAED,cAAc,EAAE;QACd,WAAW,EAAE,0EAA0E;QACvF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,wDAAwD,CAAC;SACxH,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAAiC,EAAE,EAAE;YACxE,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa;gBACrC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,2DAA2D,CAAC;YAEhE,MAAM,KAAK,GAAG;;;;;;;;;;;;UAYV,YAAY;;;;OAIf,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,eAAe,EAAE;QACf,WAAW,EAAE,mFAAmF;QAChG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG;;;;;;;;;;;;;OAab,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { z } from 'zod';
2
+ import { MssqlClient } from '../mssqlClient.js';
3
+ export declare const healthTools: {
4
+ get_database_states: {
5
+ description: string;
6
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
7
+ handler: (client: MssqlClient) => Promise<{
8
+ summary: {
9
+ total: number;
10
+ critical: number;
11
+ warning: number;
12
+ healthy: number;
13
+ };
14
+ databases: {
15
+ health_status: string;
16
+ }[];
17
+ }>;
18
+ };
19
+ get_disk_space: {
20
+ description: string;
21
+ inputSchema: z.ZodObject<{
22
+ database: z.ZodOptional<z.ZodString>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ database?: string | undefined;
25
+ }, {
26
+ database?: string | undefined;
27
+ }>;
28
+ handler: (client: MssqlClient, args: {
29
+ database?: string;
30
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
31
+ };
32
+ get_memory_usage: {
33
+ description: string;
34
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
35
+ handler: (client: MssqlClient) => Promise<{
36
+ serverMemory: import("mssql").IRecordSet<unknown>;
37
+ topMemoryClerks: import("mssql").IRecordSet<unknown>[];
38
+ bufferPoolByDatabase: import("mssql").IRecordSet<unknown>[];
39
+ }>;
40
+ };
41
+ get_log_space: {
42
+ description: string;
43
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
44
+ handler: (client: MssqlClient) => Promise<{
45
+ summary: {
46
+ total: number;
47
+ critical: number;
48
+ warning: number;
49
+ };
50
+ databases: {
51
+ health: string;
52
+ 'Database Name': string;
53
+ 'Log Size (MB)': number;
54
+ 'Log Space Used (%)': number;
55
+ Status: number;
56
+ }[];
57
+ }>;
58
+ };
59
+ get_backup_status: {
60
+ description: string;
61
+ inputSchema: z.ZodObject<{
62
+ maxAgeDays: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
63
+ }, "strip", z.ZodTypeAny, {
64
+ maxAgeDays: number;
65
+ }, {
66
+ maxAgeDays?: number | undefined;
67
+ }>;
68
+ handler: (client: MssqlClient, args: {
69
+ maxAgeDays?: number;
70
+ }) => Promise<{
71
+ summary: {
72
+ total: number;
73
+ neverBackedUp: number;
74
+ stale: number;
75
+ };
76
+ databases: {
77
+ health: string;
78
+ database_name: string;
79
+ recovery_model: string;
80
+ last_full_backup: Date | null;
81
+ last_diff_backup: Date | null;
82
+ last_log_backup: Date | null;
83
+ days_since_full: number | null;
84
+ hours_since_log: number | null;
85
+ }[];
86
+ }>;
87
+ };
88
+ };
89
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/tools/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,eAAO,MAAM,WAAW;;;;0BAII,WAAW;;;;;;;;+BAwBkB,MAAM;;;;;;;;;;;;;0BAqBnC,WAAW,QAAQ;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;0BAmCxC,WAAW;;;;;;;;;0BAiDX,WAAW;;;;;;;;iCAMd,MAAM;iCACN,MAAM;sCACD,MAAM;wBACpB,MAAM;;;;;;;;;;;;;0BA+BM,WAAW,QAAQ;YAAE,UAAU,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;+BAqB/C,MAAM;gCACL,MAAM;kCACJ,IAAI,GAAG,IAAI;kCACX,IAAI,GAAG,IAAI;iCACZ,IAAI,GAAG,IAAI;iCACX,MAAM,GAAG,IAAI;iCACb,MAAM,GAAG,IAAI;;;;CAwBrC,CAAC"}
@@ -0,0 +1,189 @@
1
+ import { z } from 'zod';
2
+ export const healthTools = {
3
+ get_database_states: {
4
+ description: 'Get the health status of all databases including any that are offline, recovering, or suspect',
5
+ inputSchema: z.object({}),
6
+ handler: async (client) => {
7
+ const query = `
8
+ SELECT
9
+ name,
10
+ database_id,
11
+ state_desc as state,
12
+ user_access_desc as user_access,
13
+ is_read_only,
14
+ is_auto_close_on,
15
+ is_auto_shrink_on,
16
+ recovery_model_desc as recovery_model,
17
+ log_reuse_wait_desc as log_reuse_wait,
18
+ CASE
19
+ WHEN state_desc != 'ONLINE' THEN 'CRITICAL'
20
+ WHEN is_auto_shrink_on = 1 THEN 'WARNING'
21
+ WHEN log_reuse_wait_desc NOT IN ('NOTHING', 'LOG_BACKUP') THEN 'WARNING'
22
+ ELSE 'OK'
23
+ END as health_status
24
+ FROM sys.databases
25
+ ORDER BY
26
+ CASE WHEN state_desc != 'ONLINE' THEN 0 ELSE 1 END,
27
+ name
28
+ `;
29
+ const result = await client.query(query);
30
+ const critical = result.filter((r) => r.health_status === 'CRITICAL');
31
+ const warning = result.filter((r) => r.health_status === 'WARNING');
32
+ return {
33
+ summary: {
34
+ total: result.length,
35
+ critical: critical.length,
36
+ warning: warning.length,
37
+ healthy: result.length - critical.length - warning.length,
38
+ },
39
+ databases: result,
40
+ };
41
+ },
42
+ },
43
+ get_disk_space: {
44
+ description: 'Get disk space usage for all database files including data and log files',
45
+ inputSchema: z.object({
46
+ database: z.string().optional().describe('Specific database to check (optional, checks all if not specified)'),
47
+ }),
48
+ handler: async (client, args) => {
49
+ const dbFilter = args.database ? `AND DB_NAME(database_id) = '${args.database}'` : '';
50
+ const query = `
51
+ SELECT
52
+ DB_NAME(database_id) as database_name,
53
+ name as file_name,
54
+ physical_name as file_path,
55
+ type_desc as file_type,
56
+ CAST(size * 8.0 / 1024 AS DECIMAL(10,2)) as size_mb,
57
+ CAST(FILEPROPERTY(name, 'SpaceUsed') * 8.0 / 1024 AS DECIMAL(10,2)) as used_mb,
58
+ CAST((size - FILEPROPERTY(name, 'SpaceUsed')) * 8.0 / 1024 AS DECIMAL(10,2)) as free_mb,
59
+ CAST(100.0 * FILEPROPERTY(name, 'SpaceUsed') / size AS DECIMAL(5,2)) as used_percent,
60
+ CASE max_size
61
+ WHEN -1 THEN 'Unlimited'
62
+ WHEN 0 THEN 'No growth'
63
+ ELSE CAST(CAST(max_size * 8.0 / 1024 AS DECIMAL(10,2)) AS VARCHAR) + ' MB'
64
+ END as max_size,
65
+ CASE is_percent_growth
66
+ WHEN 1 THEN CAST(growth AS VARCHAR) + '%'
67
+ ELSE CAST(growth * 8 / 1024 AS VARCHAR) + ' MB'
68
+ END as growth_increment
69
+ FROM sys.master_files
70
+ WHERE database_id > 0
71
+ ${dbFilter}
72
+ ORDER BY database_name, type_desc
73
+ `;
74
+ return await client.query(query);
75
+ },
76
+ },
77
+ get_memory_usage: {
78
+ description: 'Get SQL Server memory usage including buffer pool, plan cache, and other memory clerks',
79
+ inputSchema: z.object({}),
80
+ handler: async (client) => {
81
+ const query = `
82
+ SELECT
83
+ type as memory_clerk_type,
84
+ name as memory_clerk_name,
85
+ CAST(pages_kb / 1024.0 AS DECIMAL(10,2)) as size_mb,
86
+ CAST(100.0 * pages_kb / SUM(pages_kb) OVER() AS DECIMAL(5,2)) as pct_of_total
87
+ FROM sys.dm_os_memory_clerks
88
+ WHERE pages_kb > 0
89
+ ORDER BY pages_kb DESC
90
+ `;
91
+ const clerks = await client.query(query);
92
+ // Get overall memory status
93
+ const memoryQuery = `
94
+ SELECT
95
+ physical_memory_kb / 1024 as physical_memory_mb,
96
+ committed_kb / 1024 as committed_mb,
97
+ committed_target_kb / 1024 as committed_target_mb,
98
+ visible_target_kb / 1024 as visible_target_mb
99
+ FROM sys.dm_os_sys_info
100
+ `;
101
+ const memoryInfo = await client.query(memoryQuery);
102
+ // Get buffer pool usage
103
+ const bufferQuery = `
104
+ SELECT
105
+ DB_NAME(database_id) as database_name,
106
+ COUNT(*) * 8 / 1024 as buffer_pool_mb
107
+ FROM sys.dm_os_buffer_descriptors
108
+ GROUP BY database_id
109
+ ORDER BY COUNT(*) DESC
110
+ `;
111
+ const bufferUsage = await client.query(bufferQuery);
112
+ return {
113
+ serverMemory: memoryInfo[0],
114
+ topMemoryClerks: clerks.slice(0, 15),
115
+ bufferPoolByDatabase: bufferUsage,
116
+ };
117
+ },
118
+ },
119
+ get_log_space: {
120
+ description: 'Get transaction log space usage for all databases',
121
+ inputSchema: z.object({}),
122
+ handler: async (client) => {
123
+ const query = `
124
+ DBCC SQLPERF(LOGSPACE) WITH NO_INFOMSGS
125
+ `;
126
+ const result = await client.query(query);
127
+ // Add health assessment
128
+ const assessed = result.map((r) => ({
129
+ ...r,
130
+ health: r['Log Space Used (%)'] > 90 ? 'CRITICAL' :
131
+ r['Log Space Used (%)'] > 75 ? 'WARNING' : 'OK',
132
+ }));
133
+ const critical = assessed.filter((r) => r.health === 'CRITICAL');
134
+ const warning = assessed.filter((r) => r.health === 'WARNING');
135
+ return {
136
+ summary: {
137
+ total: assessed.length,
138
+ critical: critical.length,
139
+ warning: warning.length,
140
+ },
141
+ databases: assessed,
142
+ };
143
+ },
144
+ },
145
+ get_backup_status: {
146
+ description: 'Get last backup information for all databases',
147
+ inputSchema: z.object({
148
+ maxAgeDays: z.number().optional().default(7).describe('Flag databases with no backup in this many days as warning'),
149
+ }),
150
+ handler: async (client, args) => {
151
+ const query = `
152
+ SELECT
153
+ d.name as database_name,
154
+ d.recovery_model_desc as recovery_model,
155
+ MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) as last_full_backup,
156
+ MAX(CASE WHEN b.type = 'I' THEN b.backup_finish_date END) as last_diff_backup,
157
+ MAX(CASE WHEN b.type = 'L' THEN b.backup_finish_date END) as last_log_backup,
158
+ DATEDIFF(DAY, MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END), GETDATE()) as days_since_full,
159
+ DATEDIFF(HOUR, MAX(CASE WHEN b.type = 'L' THEN b.backup_finish_date END), GETDATE()) as hours_since_log
160
+ FROM sys.databases d
161
+ LEFT JOIN msdb.dbo.backupset b ON d.name = b.database_name
162
+ WHERE d.database_id > 4 -- Exclude system databases
163
+ AND d.state_desc = 'ONLINE'
164
+ GROUP BY d.name, d.recovery_model_desc
165
+ ORDER BY
166
+ CASE WHEN MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) IS NULL THEN 0 ELSE 1 END,
167
+ MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END)
168
+ `;
169
+ const result = await client.query(query);
170
+ // Add health assessment
171
+ const maxAge = args.maxAgeDays || 7;
172
+ const assessed = result.map((r) => ({
173
+ ...r,
174
+ health: r.days_since_full === null ? 'CRITICAL' :
175
+ r.days_since_full > maxAge ? 'WARNING' :
176
+ (r.recovery_model === 'FULL' && (r.hours_since_log === null || r.hours_since_log > 24)) ? 'WARNING' : 'OK',
177
+ }));
178
+ return {
179
+ summary: {
180
+ total: assessed.length,
181
+ neverBackedUp: assessed.filter((r) => r.days_since_full === null).length,
182
+ stale: assessed.filter((r) => r.days_since_full !== null && r.days_since_full > maxAge).length,
183
+ },
184
+ databases: assessed,
185
+ };
186
+ },
187
+ },
188
+ };
189
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/tools/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { connectionTools } from './connection.js';
2
+ export { queryTools } from './queries.js';
3
+ export { performanceTools } from './performance.js';
4
+ export { healthTools } from './health.js';
5
+ export { jobTools } from './jobs.js';
6
+ export { availabilityTools } from './availability.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { connectionTools } from './connection.js';
2
+ export { queryTools } from './queries.js';
3
+ export { performanceTools } from './performance.js';
4
+ export { healthTools } from './health.js';
5
+ export { jobTools } from './jobs.js';
6
+ export { availabilityTools } from './availability.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { MssqlClient } from '../mssqlClient.js';
3
+ export declare const jobTools: {
4
+ list_jobs: {
5
+ description: string;
6
+ inputSchema: z.ZodObject<{
7
+ enabledOnly: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ enabledOnly: boolean;
10
+ }, {
11
+ enabledOnly?: boolean | undefined;
12
+ }>;
13
+ handler: (client: MssqlClient, args: {
14
+ enabledOnly?: boolean;
15
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
16
+ };
17
+ get_running_jobs: {
18
+ description: string;
19
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
20
+ handler: (client: MssqlClient) => Promise<import("mssql").IRecordSet<unknown>[]>;
21
+ };
22
+ get_failed_jobs: {
23
+ description: string;
24
+ inputSchema: z.ZodObject<{
25
+ hours: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ hours: number;
28
+ }, {
29
+ hours?: number | undefined;
30
+ }>;
31
+ handler: (client: MssqlClient, args: {
32
+ hours?: number;
33
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
34
+ };
35
+ get_job_history: {
36
+ description: string;
37
+ inputSchema: z.ZodObject<{
38
+ jobName: z.ZodString;
39
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
40
+ }, "strip", z.ZodTypeAny, {
41
+ top: number;
42
+ jobName: string;
43
+ }, {
44
+ jobName: string;
45
+ top?: number | undefined;
46
+ }>;
47
+ handler: (client: MssqlClient, args: {
48
+ jobName: string;
49
+ top?: number;
50
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
51
+ };
52
+ };
53
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,eAAO,MAAM,QAAQ;;;;;;;;;;0BAMO,WAAW,QAAQ;YAAE,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE;;;;;0BAiE5C,WAAW;;;;;;;;;;;0BA8BX,WAAW,QAAQ;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;0BAmCrC,WAAW,QAAQ;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE;;CA8B/E,CAAC"}