@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,161 @@
1
+ import { z } from 'zod';
2
+ export const jobTools = {
3
+ list_jobs: {
4
+ description: 'List all SQL Server Agent jobs with their status and schedule',
5
+ inputSchema: z.object({
6
+ enabledOnly: z.boolean().optional().default(false).describe('Only show enabled jobs'),
7
+ }),
8
+ handler: async (client, args) => {
9
+ const enabledFilter = args.enabledOnly ? 'AND j.enabled = 1' : '';
10
+ const query = `
11
+ SELECT
12
+ j.job_id,
13
+ j.name as job_name,
14
+ j.description,
15
+ CASE j.enabled WHEN 1 THEN 'Enabled' ELSE 'Disabled' END as status,
16
+ c.name as category,
17
+ SUSER_SNAME(j.owner_sid) as owner,
18
+ j.date_created,
19
+ j.date_modified,
20
+ CASE
21
+ WHEN ja.run_requested_date IS NOT NULL AND ja.stop_execution_date IS NULL THEN 'Running'
22
+ ELSE 'Idle'
23
+ END as current_status,
24
+ h.last_run_date,
25
+ h.last_run_time,
26
+ h.last_run_outcome,
27
+ h.last_run_duration_seconds
28
+ FROM msdb.dbo.sysjobs j
29
+ LEFT JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
30
+ LEFT JOIN msdb.dbo.sysjobactivity ja ON j.job_id = ja.job_id
31
+ AND ja.session_id = (SELECT MAX(session_id) FROM msdb.dbo.sysjobactivity)
32
+ LEFT JOIN (
33
+ SELECT
34
+ job_id,
35
+ MAX(CAST(
36
+ CAST(run_date AS VARCHAR) + ' ' +
37
+ STUFF(STUFF(RIGHT('000000' + CAST(run_time AS VARCHAR), 6), 5, 0, ':'), 3, 0, ':')
38
+ AS DATETIME)) as last_run_date,
39
+ MAX(run_time) as last_run_time,
40
+ (SELECT TOP 1 CASE run_status
41
+ WHEN 0 THEN 'Failed'
42
+ WHEN 1 THEN 'Succeeded'
43
+ WHEN 2 THEN 'Retry'
44
+ WHEN 3 THEN 'Canceled'
45
+ WHEN 4 THEN 'In Progress'
46
+ END FROM msdb.dbo.sysjobhistory h2
47
+ WHERE h2.job_id = h.job_id AND h2.step_id = 0
48
+ ORDER BY run_date DESC, run_time DESC) as last_run_outcome,
49
+ (SELECT TOP 1
50
+ ((run_duration / 10000) * 3600) +
51
+ (((run_duration % 10000) / 100) * 60) +
52
+ (run_duration % 100)
53
+ FROM msdb.dbo.sysjobhistory h2
54
+ WHERE h2.job_id = h.job_id AND h2.step_id = 0
55
+ ORDER BY run_date DESC, run_time DESC) as last_run_duration_seconds
56
+ FROM msdb.dbo.sysjobhistory h
57
+ WHERE step_id = 0
58
+ GROUP BY job_id
59
+ ) h ON j.job_id = h.job_id
60
+ WHERE 1=1
61
+ ${enabledFilter}
62
+ ORDER BY j.name
63
+ `;
64
+ return await client.query(query);
65
+ },
66
+ },
67
+ get_running_jobs: {
68
+ description: 'Get currently executing SQL Server Agent jobs',
69
+ inputSchema: z.object({}),
70
+ handler: async (client) => {
71
+ const query = `
72
+ SELECT
73
+ j.name as job_name,
74
+ j.job_id,
75
+ ja.start_execution_date,
76
+ DATEDIFF(SECOND, ja.start_execution_date, GETDATE()) as running_seconds,
77
+ ISNULL(ja.last_executed_step_id, 0) as current_step,
78
+ js.step_name as current_step_name,
79
+ js.subsystem,
80
+ js.command as step_command
81
+ FROM msdb.dbo.sysjobactivity ja
82
+ INNER JOIN msdb.dbo.sysjobs j ON ja.job_id = j.job_id
83
+ LEFT JOIN msdb.dbo.sysjobsteps js ON j.job_id = js.job_id
84
+ AND ja.last_executed_step_id + 1 = js.step_id
85
+ WHERE ja.session_id = (SELECT MAX(session_id) FROM msdb.dbo.syssessions)
86
+ AND ja.start_execution_date IS NOT NULL
87
+ AND ja.stop_execution_date IS NULL
88
+ ORDER BY ja.start_execution_date
89
+ `;
90
+ return await client.query(query);
91
+ },
92
+ },
93
+ get_failed_jobs: {
94
+ description: 'Get jobs that failed in their last execution or recent history',
95
+ inputSchema: z.object({
96
+ hours: z.number().optional().default(24).describe('Look back this many hours for failures'),
97
+ }),
98
+ handler: async (client, args) => {
99
+ const query = `
100
+ SELECT
101
+ j.name as job_name,
102
+ j.job_id,
103
+ h.step_id,
104
+ h.step_name,
105
+ CAST(
106
+ CAST(h.run_date AS VARCHAR) + ' ' +
107
+ STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR), 6), 5, 0, ':'), 3, 0, ':')
108
+ AS DATETIME) as run_datetime,
109
+ ((h.run_duration / 10000) * 3600) +
110
+ (((h.run_duration % 10000) / 100) * 60) +
111
+ (h.run_duration % 100) as duration_seconds,
112
+ h.message as error_message
113
+ FROM msdb.dbo.sysjobhistory h
114
+ INNER JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
115
+ WHERE h.run_status = 0 -- Failed
116
+ AND CAST(
117
+ CAST(h.run_date AS VARCHAR) + ' ' +
118
+ STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR), 6), 5, 0, ':'), 3, 0, ':')
119
+ AS DATETIME) > DATEADD(HOUR, -${args.hours || 24}, GETDATE())
120
+ ORDER BY h.run_date DESC, h.run_time DESC
121
+ `;
122
+ return await client.query(query);
123
+ },
124
+ },
125
+ get_job_history: {
126
+ description: 'Get execution history for a specific job',
127
+ inputSchema: z.object({
128
+ jobName: z.string().describe('Name of the job'),
129
+ top: z.number().optional().default(50).describe('Number of history records to return'),
130
+ }),
131
+ handler: async (client, args) => {
132
+ const query = `
133
+ SELECT TOP ${args.top || 50}
134
+ j.name as job_name,
135
+ h.step_id,
136
+ h.step_name,
137
+ CASE h.run_status
138
+ WHEN 0 THEN 'Failed'
139
+ WHEN 1 THEN 'Succeeded'
140
+ WHEN 2 THEN 'Retry'
141
+ WHEN 3 THEN 'Canceled'
142
+ WHEN 4 THEN 'In Progress'
143
+ END as status,
144
+ CAST(
145
+ CAST(h.run_date AS VARCHAR) + ' ' +
146
+ STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR), 6), 5, 0, ':'), 3, 0, ':')
147
+ AS DATETIME) as run_datetime,
148
+ ((h.run_duration / 10000) * 3600) +
149
+ (((h.run_duration % 10000) / 100) * 60) +
150
+ (h.run_duration % 100) as duration_seconds,
151
+ h.message
152
+ FROM msdb.dbo.sysjobhistory h
153
+ INNER JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
154
+ WHERE j.name = @jobName
155
+ ORDER BY h.run_date DESC, h.run_time DESC, h.step_id
156
+ `;
157
+ return await client.query(query, { jobName: args.jobName });
158
+ },
159
+ },
160
+ };
161
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,SAAS,EAAE;QACT,WAAW,EAAE,+DAA+D;QAC5E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACtF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAA+B,EAAE,EAAE;YACtE,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;YAElE,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAmDV,aAAa;;OAEhB,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,gBAAgB,EAAE;QAChB,WAAW,EAAE,+CAA+C;QAC5D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;OAkBb,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,eAAe,EAAE;QACf,WAAW,EAAE,gEAAgE;QAC7E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;SAC5F,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAAwB,EAAE,EAAE;YAC/D,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;wCAoBoB,IAAI,CAAC,KAAK,IAAI,EAAE;;OAEjD,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,eAAe,EAAE;QACf,WAAW,EAAE,0CAA0C;QACvD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC/C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;SACvF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAAuC,EAAE,EAAE;YAC9E,MAAM,KAAK,GAAG;qBACC,IAAI,CAAC,GAAG,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;OAuB5B,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { z } from 'zod';
2
+ import { MssqlClient } from '../mssqlClient.js';
3
+ export declare const performanceTools: {
4
+ get_blocking: {
5
+ description: string;
6
+ inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
7
+ handler: (client: MssqlClient) => Promise<{
8
+ blockingCount: number;
9
+ chains: import("mssql").IRecordSet<unknown>[];
10
+ }>;
11
+ };
12
+ get_wait_stats: {
13
+ description: string;
14
+ inputSchema: z.ZodObject<{
15
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
16
+ excludeIdle: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ top: number;
19
+ excludeIdle: boolean;
20
+ }, {
21
+ top?: number | undefined;
22
+ excludeIdle?: boolean | undefined;
23
+ }>;
24
+ handler: (client: MssqlClient, args: {
25
+ top?: number;
26
+ excludeIdle?: boolean;
27
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
28
+ };
29
+ get_cpu_usage: {
30
+ description: string;
31
+ inputSchema: z.ZodObject<{
32
+ minutes: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ minutes: number;
35
+ }, {
36
+ minutes?: number | undefined;
37
+ }>;
38
+ handler: (client: MssqlClient, args: {
39
+ minutes?: number;
40
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
41
+ };
42
+ get_index_usage: {
43
+ description: string;
44
+ inputSchema: z.ZodObject<{
45
+ database: z.ZodString;
46
+ showUnused: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ database: string;
49
+ showUnused: boolean;
50
+ }, {
51
+ database: string;
52
+ showUnused?: boolean | undefined;
53
+ }>;
54
+ handler: (client: MssqlClient, args: {
55
+ database: string;
56
+ showUnused?: boolean;
57
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
58
+ };
59
+ };
60
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,eAAO,MAAM,gBAAgB;;;;0BAID,WAAW;;;;;;;;;;;;;;;;;0BAoDX,WAAW,QAAQ;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE;;;;;;;;;;;0BA2C1D,WAAW,QAAQ;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;0BAmCvC,WAAW,QAAQ;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,OAAO,CAAA;SAAE;;CAkCxF,CAAC"}
@@ -0,0 +1,162 @@
1
+ import { z } from 'zod';
2
+ export const performanceTools = {
3
+ get_blocking: {
4
+ description: 'Get current blocking chains showing blocked and blocking sessions',
5
+ inputSchema: z.object({}),
6
+ handler: async (client) => {
7
+ const query = `
8
+ WITH BlockingTree AS (
9
+ SELECT
10
+ r.session_id as blocked_session_id,
11
+ r.blocking_session_id,
12
+ s.login_name as blocked_login,
13
+ s.host_name as blocked_host,
14
+ s.program_name as blocked_program,
15
+ DB_NAME(r.database_id) as database_name,
16
+ r.wait_type,
17
+ r.wait_time / 1000.0 as wait_time_seconds,
18
+ r.wait_resource,
19
+ SUBSTRING(st.text, (r.statement_start_offset/2)+1,
20
+ ((CASE r.statement_end_offset
21
+ WHEN -1 THEN DATALENGTH(st.text)
22
+ ELSE r.statement_end_offset
23
+ END - r.statement_start_offset)/2)+1) as blocked_query
24
+ FROM sys.dm_exec_requests r
25
+ INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
26
+ CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
27
+ WHERE r.blocking_session_id > 0
28
+ )
29
+ SELECT
30
+ bt.*,
31
+ bs.login_name as blocking_login,
32
+ bs.host_name as blocking_host,
33
+ bs.program_name as blocking_program,
34
+ COALESCE(
35
+ (SELECT TOP 1 text FROM sys.dm_exec_sql_text(bc.most_recent_sql_handle)),
36
+ 'No query available'
37
+ ) as blocking_query
38
+ FROM BlockingTree bt
39
+ LEFT JOIN sys.dm_exec_sessions bs ON bt.blocking_session_id = bs.session_id
40
+ LEFT JOIN sys.dm_exec_connections bc ON bt.blocking_session_id = bc.session_id
41
+ ORDER BY bt.wait_time_seconds DESC
42
+ `;
43
+ const result = await client.query(query);
44
+ return {
45
+ blockingCount: result.length,
46
+ chains: result,
47
+ };
48
+ },
49
+ },
50
+ get_wait_stats: {
51
+ description: 'Get aggregated wait statistics to identify performance bottlenecks',
52
+ inputSchema: z.object({
53
+ top: z.number().optional().default(20).describe('Number of top waits to return'),
54
+ excludeIdle: z.boolean().optional().default(true).describe('Exclude idle and benign waits'),
55
+ }),
56
+ handler: async (client, args) => {
57
+ const excludeFilter = args.excludeIdle
58
+ ? `WHERE wait_type NOT IN (
59
+ 'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
60
+ 'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
61
+ 'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',
62
+ 'BROKER_TO_FLUSH', 'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT',
63
+ 'CLR_AUTO_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
64
+ 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'BROKER_EVENTHANDLER',
65
+ 'TRACEWRITE', 'FT_IFTSHC_MUTEX', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
66
+ 'BROKER_RECEIVE_WAITFOR', 'ONDEMAND_TASK_QUEUE', 'DBMIRROR_EVENTS_QUEUE',
67
+ 'DBMIRRORING_CMD', 'BROKER_TRANSMITTER', 'SQLTRACE_WAIT_ENTRIES',
68
+ 'SLEEP_BPOOL_FLUSH', 'SQLTRACE_LOCK', 'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
69
+ 'DIRTY_PAGE_POLL', 'SP_SERVER_DIAGNOSTICS_SLEEP'
70
+ )
71
+ AND wait_type NOT LIKE 'PREEMPTIVE_%'
72
+ AND wait_type NOT LIKE 'BROKER_%'
73
+ AND wait_type NOT LIKE 'SLEEP_%'`
74
+ : '';
75
+ const query = `
76
+ SELECT TOP ${args.top || 20}
77
+ wait_type,
78
+ waiting_tasks_count,
79
+ wait_time_ms,
80
+ max_wait_time_ms,
81
+ signal_wait_time_ms,
82
+ wait_time_ms - signal_wait_time_ms as resource_wait_time_ms,
83
+ CAST(100.0 * wait_time_ms / SUM(wait_time_ms) OVER() AS DECIMAL(5,2)) as pct_of_total
84
+ FROM sys.dm_os_wait_stats
85
+ ${excludeFilter}
86
+ ORDER BY wait_time_ms DESC
87
+ `;
88
+ return await client.query(query);
89
+ },
90
+ },
91
+ get_cpu_usage: {
92
+ description: 'Get CPU usage history for SQL Server from ring buffer',
93
+ inputSchema: z.object({
94
+ minutes: z.number().optional().default(30).describe('Minutes of history to retrieve'),
95
+ }),
96
+ handler: async (client, args) => {
97
+ const query = `
98
+ DECLARE @ts_now BIGINT = (SELECT cpu_ticks/(cpu_ticks/ms_ticks) FROM sys.dm_os_sys_info);
99
+
100
+ SELECT TOP ${args.minutes || 30}
101
+ DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) as event_time,
102
+ SQLProcessUtilization as sql_cpu_percent,
103
+ SystemIdle as system_idle_percent,
104
+ 100 - SystemIdle - SQLProcessUtilization as other_cpu_percent
105
+ FROM (
106
+ SELECT
107
+ record.value('(./Record/@id)[1]', 'int') as record_id,
108
+ record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') as SystemIdle,
109
+ record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') as SQLProcessUtilization,
110
+ [timestamp]
111
+ FROM (
112
+ SELECT [timestamp], CONVERT(xml, record) as record
113
+ FROM sys.dm_os_ring_buffers
114
+ WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
115
+ AND record LIKE '%<SystemHealth>%'
116
+ ) AS x
117
+ ) AS y
118
+ ORDER BY record_id DESC
119
+ `;
120
+ return await client.query(query);
121
+ },
122
+ },
123
+ get_index_usage: {
124
+ description: 'Get index usage statistics to identify unused or missing indexes',
125
+ inputSchema: z.object({
126
+ database: z.string().describe('Database name to analyze'),
127
+ showUnused: z.boolean().optional().default(true).describe('Include unused indexes'),
128
+ }),
129
+ handler: async (client, args) => {
130
+ const unusedFilter = args.showUnused
131
+ ? ''
132
+ : 'AND (user_seeks + user_scans + user_lookups) > 0';
133
+ const query = `
134
+ USE [${args.database}];
135
+
136
+ SELECT
137
+ OBJECT_SCHEMA_NAME(i.object_id) as schema_name,
138
+ OBJECT_NAME(i.object_id) as table_name,
139
+ i.name as index_name,
140
+ i.type_desc as index_type,
141
+ ISNULL(s.user_seeks, 0) as user_seeks,
142
+ ISNULL(s.user_scans, 0) as user_scans,
143
+ ISNULL(s.user_lookups, 0) as user_lookups,
144
+ ISNULL(s.user_updates, 0) as user_updates,
145
+ ISNULL(s.last_user_seek, '1900-01-01') as last_user_seek,
146
+ ISNULL(s.last_user_scan, '1900-01-01') as last_user_scan,
147
+ CAST(ps.used_page_count * 8.0 / 1024 AS DECIMAL(10,2)) as size_mb
148
+ FROM sys.indexes i
149
+ LEFT JOIN sys.dm_db_index_usage_stats s
150
+ ON i.object_id = s.object_id AND i.index_id = s.index_id AND s.database_id = DB_ID()
151
+ LEFT JOIN sys.dm_db_partition_stats ps
152
+ ON i.object_id = ps.object_id AND i.index_id = ps.index_id
153
+ WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1
154
+ AND i.index_id > 0
155
+ ${unusedFilter}
156
+ ORDER BY (ISNULL(s.user_seeks, 0) + ISNULL(s.user_scans, 0) + ISNULL(s.user_lookups, 0)) ASC
157
+ `;
158
+ return await client.query(query);
159
+ },
160
+ },
161
+ };
162
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,YAAY,EAAE;QACZ,WAAW,EAAE,mEAAmE;QAChF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCb,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACzC,OAAO;gBACL,aAAa,EAAE,MAAM,CAAC,MAAM;gBAC5B,MAAM,EAAE,MAAM;aACf,CAAC;QACJ,CAAC;KACF;IAED,cAAc,EAAE;QACd,WAAW,EAAE,oEAAoE;QACjF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAChF,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;SAC5F,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAA6C,EAAE,EAAE;YACpF,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW;gBACpC,CAAC,CAAC;;;;;;;;;;;;;;;2CAeiC;gBACnC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,KAAK,GAAG;qBACC,IAAI,CAAC,GAAG,IAAI,EAAE;;;;;;;;;UASzB,aAAa;;OAEhB,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,aAAa,EAAE;QACb,WAAW,EAAE,uDAAuD;QACpE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;SACtF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAA0B,EAAE,EAAE;YACjE,MAAM,KAAK,GAAG;;;qBAGC,IAAI,CAAC,OAAO,IAAI,EAAE;;;;;;;;;;;;;;;;;;;OAmBhC,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;IAED,eAAe,EAAE;QACf,WAAW,EAAE,kEAAkE;QAC/E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;YACzD,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACpF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,MAAmB,EAAE,IAAgD,EAAE,EAAE;YACvF,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU;gBAClC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,kDAAkD,CAAC;YAEvD,MAAM,KAAK,GAAG;eACL,IAAI,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;UAqBlB,YAAY;;OAEf,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { MssqlClient } from '../mssqlClient.js';
3
+ export declare const queryTools: {
4
+ execute_query: {
5
+ description: string;
6
+ inputSchema: z.ZodObject<{
7
+ query: z.ZodString;
8
+ database: z.ZodOptional<z.ZodString>;
9
+ maxRows: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ query: string;
12
+ maxRows: number;
13
+ database?: string | undefined;
14
+ }, {
15
+ query: string;
16
+ database?: string | undefined;
17
+ maxRows?: number | undefined;
18
+ }>;
19
+ handler: (client: MssqlClient, args: {
20
+ query: string;
21
+ database?: string;
22
+ maxRows?: number;
23
+ }) => Promise<{
24
+ rowCount: number;
25
+ rows: import("mssql").IRecordSet<unknown>[];
26
+ }>;
27
+ };
28
+ get_expensive_queries: {
29
+ description: string;
30
+ inputSchema: z.ZodObject<{
31
+ metric: z.ZodDefault<z.ZodOptional<z.ZodEnum<["cpu", "reads", "writes", "duration", "executions"]>>>;
32
+ top: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ metric: "cpu" | "reads" | "writes" | "duration" | "executions";
35
+ top: number;
36
+ }, {
37
+ metric?: "cpu" | "reads" | "writes" | "duration" | "executions" | undefined;
38
+ top?: number | undefined;
39
+ }>;
40
+ handler: (client: MssqlClient, args: {
41
+ metric?: string;
42
+ top?: number;
43
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
44
+ };
45
+ get_running_queries: {
46
+ description: string;
47
+ inputSchema: z.ZodObject<{
48
+ includeSystem: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ includeSystem: boolean;
51
+ }, {
52
+ includeSystem?: boolean | undefined;
53
+ }>;
54
+ handler: (client: MssqlClient, args: {
55
+ includeSystem?: boolean;
56
+ }) => Promise<import("mssql").IRecordSet<unknown>[]>;
57
+ };
58
+ };
59
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/tools/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;0BAQK,WAAW,QAAQ;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;;;;;;;0BA0CzE,WAAW,QAAQ;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE;;;;;;;;;;;0BA2CpD,WAAW,QAAQ;YAAE,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE;;CAyCzE,CAAC"}
@@ -0,0 +1,125 @@
1
+ import { z } from 'zod';
2
+ export const queryTools = {
3
+ execute_query: {
4
+ description: 'Execute a read-only SQL query. Only SELECT statements are allowed for safety.',
5
+ inputSchema: z.object({
6
+ query: z.string().describe('The SQL SELECT query to execute'),
7
+ database: z.string().optional().describe('Database to run the query against (optional, uses default if not specified)'),
8
+ maxRows: z.number().optional().default(1000).describe('Maximum rows to return (default: 1000)'),
9
+ }),
10
+ handler: async (client, args) => {
11
+ // Safety check: only allow SELECT statements
12
+ const trimmedQuery = args.query.trim().toUpperCase();
13
+ if (!trimmedQuery.startsWith('SELECT') && !trimmedQuery.startsWith('WITH')) {
14
+ throw new Error('Only SELECT queries are allowed. For safety, INSERT/UPDATE/DELETE/EXEC are not permitted.');
15
+ }
16
+ // Check for dangerous keywords
17
+ const dangerous = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'TRUNCATE', 'ALTER', 'CREATE', 'EXEC', 'EXECUTE', 'XP_', 'SP_'];
18
+ for (const keyword of dangerous) {
19
+ if (trimmedQuery.includes(keyword) && !trimmedQuery.startsWith('WITH')) {
20
+ throw new Error(`Query contains forbidden keyword: ${keyword}`);
21
+ }
22
+ }
23
+ let finalQuery = args.query;
24
+ // Add TOP clause if not present and maxRows specified
25
+ if (args.maxRows && !trimmedQuery.includes('TOP')) {
26
+ finalQuery = args.query.replace(/^SELECT/i, `SELECT TOP ${args.maxRows}`);
27
+ }
28
+ // Switch database if specified
29
+ if (args.database) {
30
+ finalQuery = `USE [${args.database}]; ${finalQuery}`;
31
+ }
32
+ const result = await client.query(finalQuery);
33
+ return {
34
+ rowCount: result.length,
35
+ rows: result,
36
+ };
37
+ },
38
+ },
39
+ get_expensive_queries: {
40
+ description: 'Get the most resource-intensive queries from the query store or plan cache',
41
+ inputSchema: z.object({
42
+ metric: z.enum(['cpu', 'reads', 'writes', 'duration', 'executions']).optional().default('cpu')
43
+ .describe('Metric to sort by'),
44
+ top: z.number().optional().default(20).describe('Number of queries to return'),
45
+ }),
46
+ handler: async (client, args) => {
47
+ const orderByMap = {
48
+ cpu: 'total_worker_time',
49
+ reads: 'total_logical_reads',
50
+ writes: 'total_logical_writes',
51
+ duration: 'total_elapsed_time',
52
+ executions: 'execution_count',
53
+ };
54
+ const orderBy = orderByMap[args.metric || 'cpu'];
55
+ const query = `
56
+ SELECT TOP ${args.top || 20}
57
+ qs.execution_count,
58
+ qs.total_worker_time / 1000 as total_cpu_ms,
59
+ qs.total_worker_time / qs.execution_count / 1000 as avg_cpu_ms,
60
+ qs.total_elapsed_time / 1000 as total_duration_ms,
61
+ qs.total_elapsed_time / qs.execution_count / 1000 as avg_duration_ms,
62
+ qs.total_logical_reads,
63
+ qs.total_logical_reads / qs.execution_count as avg_logical_reads,
64
+ qs.total_logical_writes,
65
+ qs.last_execution_time,
66
+ SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
67
+ ((CASE qs.statement_end_offset
68
+ WHEN -1 THEN DATALENGTH(st.text)
69
+ ELSE qs.statement_end_offset
70
+ END - qs.statement_start_offset)/2)+1) as query_text,
71
+ DB_NAME(st.dbid) as database_name
72
+ FROM sys.dm_exec_query_stats qs
73
+ CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
74
+ WHERE qs.execution_count > 0
75
+ ORDER BY ${orderBy} DESC
76
+ `;
77
+ return await client.query(query);
78
+ },
79
+ },
80
+ get_running_queries: {
81
+ description: 'Get currently executing queries with their status and resource usage',
82
+ inputSchema: z.object({
83
+ includeSystem: z.boolean().optional().default(false).describe('Include system processes'),
84
+ }),
85
+ handler: async (client, args) => {
86
+ const systemFilter = args.includeSystem ? '' : 'AND s.is_user_process = 1';
87
+ const query = `
88
+ SELECT
89
+ r.session_id,
90
+ r.request_id,
91
+ r.start_time,
92
+ DATEDIFF(SECOND, r.start_time, GETDATE()) as duration_seconds,
93
+ r.status,
94
+ r.command,
95
+ r.database_id,
96
+ DB_NAME(r.database_id) as database_name,
97
+ r.wait_type,
98
+ r.wait_time,
99
+ r.blocking_session_id,
100
+ r.cpu_time,
101
+ r.total_elapsed_time,
102
+ r.reads,
103
+ r.writes,
104
+ r.logical_reads,
105
+ s.login_name,
106
+ s.host_name,
107
+ s.program_name,
108
+ SUBSTRING(st.text, (r.statement_start_offset/2)+1,
109
+ ((CASE r.statement_end_offset
110
+ WHEN -1 THEN DATALENGTH(st.text)
111
+ ELSE r.statement_end_offset
112
+ END - r.statement_start_offset)/2)+1) as current_statement,
113
+ st.text as full_query
114
+ FROM sys.dm_exec_requests r
115
+ INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
116
+ CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
117
+ WHERE r.session_id != @@SPID
118
+ ${systemFilter}
119
+ ORDER BY r.total_elapsed_time DESC
120
+ `;
121
+ return await client.query(query);
122
+ },
123
+ },
124
+ };
125
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/tools/queries.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@elad-nofy/mssql-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Microsoft SQL Server - Query execution, performance analysis, health monitoring",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "mssql-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "start": "node dist/index.js",
16
+ "dev": "tsc --watch",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "mssql",
22
+ "sql-server",
23
+ "database",
24
+ "model-context-protocol",
25
+ "claude",
26
+ "ai",
27
+ "observability",
28
+ "monitoring"
29
+ ],
30
+ "author": "Nof Yonany",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/elad-nofy/mssql-mcp"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/elad-nofy/mssql-mcp/issues"
38
+ },
39
+ "homepage": "https://github.com/elad-nofy/mssql-mcp#readme",
40
+ "dependencies": {
41
+ "@modelcontextprotocol/sdk": "^1.0.0",
42
+ "mssql": "^11.0.1",
43
+ "zod": "^3.24.1",
44
+ "zod-to-json-schema": "^3.25.1"
45
+ },
46
+ "devDependencies": {
47
+ "@types/mssql": "^9.1.5",
48
+ "@types/node": "^22.10.5",
49
+ "typescript": "^5.7.2"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ }
54
+ }