@sonisoft/now-sdk-ext-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 (102) hide show
  1. package/README.md +393 -0
  2. package/dist/common/connection.d.ts +42 -0
  3. package/dist/common/connection.d.ts.map +1 -0
  4. package/dist/common/connection.js +119 -0
  5. package/dist/common/connection.js.map +1 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +108 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/tools/aggregate.d.ts +20 -0
  11. package/dist/tools/aggregate.d.ts.map +1 -0
  12. package/dist/tools/aggregate.js +271 -0
  13. package/dist/tools/aggregate.js.map +1 -0
  14. package/dist/tools/app-manager.d.ts +50 -0
  15. package/dist/tools/app-manager.d.ts.map +1 -0
  16. package/dist/tools/app-manager.js +756 -0
  17. package/dist/tools/app-manager.js.map +1 -0
  18. package/dist/tools/atf.d.ts +16 -0
  19. package/dist/tools/atf.d.ts.map +1 -0
  20. package/dist/tools/atf.js +246 -0
  21. package/dist/tools/atf.js.map +1 -0
  22. package/dist/tools/attachment.d.ts +20 -0
  23. package/dist/tools/attachment.d.ts.map +1 -0
  24. package/dist/tools/attachment.js +223 -0
  25. package/dist/tools/attachment.js.map +1 -0
  26. package/dist/tools/batch.d.ts +15 -0
  27. package/dist/tools/batch.d.ts.map +1 -0
  28. package/dist/tools/batch.js +159 -0
  29. package/dist/tools/batch.js.map +1 -0
  30. package/dist/tools/cmdb.d.ts +14 -0
  31. package/dist/tools/cmdb.d.ts.map +1 -0
  32. package/dist/tools/cmdb.js +199 -0
  33. package/dist/tools/cmdb.js.map +1 -0
  34. package/dist/tools/codesearch.d.ts +31 -0
  35. package/dist/tools/codesearch.d.ts.map +1 -0
  36. package/dist/tools/codesearch.js +371 -0
  37. package/dist/tools/codesearch.js.map +1 -0
  38. package/dist/tools/discovery.d.ts +15 -0
  39. package/dist/tools/discovery.d.ts.map +1 -0
  40. package/dist/tools/discovery.js +204 -0
  41. package/dist/tools/discovery.js.map +1 -0
  42. package/dist/tools/execute-script.d.ts +9 -0
  43. package/dist/tools/execute-script.d.ts.map +1 -0
  44. package/dist/tools/execute-script.js +106 -0
  45. package/dist/tools/execute-script.js.map +1 -0
  46. package/dist/tools/find-atf-tests.d.ts +9 -0
  47. package/dist/tools/find-atf-tests.d.ts.map +1 -0
  48. package/dist/tools/find-atf-tests.js +152 -0
  49. package/dist/tools/find-atf-tests.js.map +1 -0
  50. package/dist/tools/health.d.ts +9 -0
  51. package/dist/tools/health.d.ts.map +1 -0
  52. package/dist/tools/health.js +137 -0
  53. package/dist/tools/health.js.map +1 -0
  54. package/dist/tools/lookup-app.d.ts +11 -0
  55. package/dist/tools/lookup-app.d.ts.map +1 -0
  56. package/dist/tools/lookup-app.js +242 -0
  57. package/dist/tools/lookup-app.js.map +1 -0
  58. package/dist/tools/lookup-columns.d.ts +10 -0
  59. package/dist/tools/lookup-columns.d.ts.map +1 -0
  60. package/dist/tools/lookup-columns.js +180 -0
  61. package/dist/tools/lookup-columns.js.map +1 -0
  62. package/dist/tools/lookup-table.d.ts +10 -0
  63. package/dist/tools/lookup-table.d.ts.map +1 -0
  64. package/dist/tools/lookup-table.js +150 -0
  65. package/dist/tools/lookup-table.js.map +1 -0
  66. package/dist/tools/query-batch.d.ts +16 -0
  67. package/dist/tools/query-batch.d.ts.map +1 -0
  68. package/dist/tools/query-batch.js +197 -0
  69. package/dist/tools/query-batch.js.map +1 -0
  70. package/dist/tools/query-syslog.d.ts +9 -0
  71. package/dist/tools/query-syslog.d.ts.map +1 -0
  72. package/dist/tools/query-syslog.js +127 -0
  73. package/dist/tools/query-syslog.js.map +1 -0
  74. package/dist/tools/query-table.d.ts +8 -0
  75. package/dist/tools/query-table.d.ts.map +1 -0
  76. package/dist/tools/query-table.js +137 -0
  77. package/dist/tools/query-table.js.map +1 -0
  78. package/dist/tools/schema.d.ts +24 -0
  79. package/dist/tools/schema.d.ts.map +1 -0
  80. package/dist/tools/schema.js +321 -0
  81. package/dist/tools/schema.js.map +1 -0
  82. package/dist/tools/scope.d.ts +25 -0
  83. package/dist/tools/scope.d.ts.map +1 -0
  84. package/dist/tools/scope.js +226 -0
  85. package/dist/tools/scope.js.map +1 -0
  86. package/dist/tools/scriptsync.d.ts +14 -0
  87. package/dist/tools/scriptsync.d.ts.map +1 -0
  88. package/dist/tools/scriptsync.js +167 -0
  89. package/dist/tools/scriptsync.js.map +1 -0
  90. package/dist/tools/task.d.ts +39 -0
  91. package/dist/tools/task.d.ts.map +1 -0
  92. package/dist/tools/task.js +390 -0
  93. package/dist/tools/task.js.map +1 -0
  94. package/dist/tools/updateset.d.ts +46 -0
  95. package/dist/tools/updateset.d.ts.map +1 -0
  96. package/dist/tools/updateset.js +475 -0
  97. package/dist/tools/updateset.js.map +1 -0
  98. package/dist/tools/workflow.d.ts +9 -0
  99. package/dist/tools/workflow.d.ts.map +1 -0
  100. package/dist/tools/workflow.js +164 -0
  101. package/dist/tools/workflow.js.map +1 -0
  102. package/package.json +68 -0
@@ -0,0 +1,242 @@
1
+ import { z } from "zod";
2
+ import { TableAPIRequest } from "@sonisoft/now-sdk-ext-core";
3
+ import { withConnectionRetry, isRetryableResponse, } from "../common/connection.js";
4
+ /**
5
+ * Maps sys_class_name values from the sys_scope hierarchy to
6
+ * human-readable labels for the output.
7
+ */
8
+ function classNameToLabel(sysClassName) {
9
+ switch (sysClassName) {
10
+ case "sys_app":
11
+ return "Custom App";
12
+ case "sys_store_app":
13
+ return "Store App";
14
+ default:
15
+ return "Application";
16
+ }
17
+ }
18
+ /**
19
+ * Registers the lookup_app tool on the MCP server.
20
+ *
21
+ * Searches ServiceNow for applications (scoped apps) and platform plugins
22
+ * by name, scope namespace, or plugin ID. Queries sys_scope (which covers
23
+ * both sys_app and sys_store_app via table inheritance) and sys_plugins
24
+ * in parallel.
25
+ */
26
+ export function registerLookupAppTool(server) {
27
+ server.registerTool("lookup_app", {
28
+ title: "Lookup Application or Plugin",
29
+ description: "Search for ServiceNow applications (scoped apps) and platform plugins by name, " +
30
+ "scope namespace, or plugin ID. Returns sys_id, name, scope, version, active status, " +
31
+ "and type for each match.\n\n" +
32
+ "ServiceNow uses a hierarchical table structure for packages:\n" +
33
+ "- sys_scope: All scoped applications (base table)\n" +
34
+ " - sys_app: Custom applications in development on this instance\n" +
35
+ " - sys_store_app: Applications installed from the ServiceNow Store or company app repo\n" +
36
+ "- sys_plugins: Platform plugins\n\n" +
37
+ "Key use cases:\n" +
38
+ "- Find an application's sys_id to pass as the `scope` parameter to execute_script " +
39
+ "(to run scripts within that application's scope)\n" +
40
+ "- Check whether a specific app or plugin is installed/active on the instance\n" +
41
+ "- Look up version, scope namespace, and vendor info for any application or plugin",
42
+ inputSchema: {
43
+ instance: z
44
+ .string()
45
+ .optional()
46
+ .describe("The ServiceNow instance auth alias (e.g., " +
47
+ '"dev224436", "prod"). If not provided, falls back ' +
48
+ "to the SN_AUTH_ALIAS environment variable."),
49
+ search_term: z
50
+ .string()
51
+ .describe("Name, scope namespace (e.g., \"x_acme_my_app\", \"sn_vul\"), or plugin ID " +
52
+ "(e.g., \"com.snc.vulnerability_response\") to search for. " +
53
+ "Case-insensitive partial matching (contains)."),
54
+ type: z
55
+ .enum(["all", "app", "plugin"])
56
+ .default("all")
57
+ .describe('Filter search scope. "app" searches scoped applications only (sys_scope table ' +
58
+ "which includes both custom apps and store apps), " +
59
+ '"plugin" searches platform plugins only (sys_plugins table), ' +
60
+ '"all" searches both. Default is "all".'),
61
+ active_only: z
62
+ .boolean()
63
+ .default(false)
64
+ .describe("When true, only returns active/installed applications and plugins. " +
65
+ "Default is false (returns all matches regardless of active status)."),
66
+ },
67
+ }, async ({ instance, search_term, type, active_only }) => {
68
+ try {
69
+ const results = await withConnectionRetry(instance, async (snInstance) => {
70
+ const tableApi = new TableAPIRequest(snInstance);
71
+ // Build sys_scope query with ^NQ for OR grouping across
72
+ // name, scope namespace, and short_description.
73
+ const buildScopeQuery = () => {
74
+ const prefix = active_only ? "active=true^" : "";
75
+ const parts = [
76
+ `${prefix}nameLIKE${search_term}`,
77
+ `${prefix}scopeLIKE${search_term}`,
78
+ `${prefix}short_descriptionLIKE${search_term}`,
79
+ ];
80
+ return parts.join("^NQ") + "^ORDERBYname";
81
+ };
82
+ // Build sys_plugins query with ^NQ for OR grouping across
83
+ // name and plugin id.
84
+ const buildPluginQuery = () => {
85
+ const prefix = active_only ? "active=true^" : "";
86
+ const parts = [
87
+ `${prefix}nameLIKE${search_term}`,
88
+ `${prefix}idLIKE${search_term}`,
89
+ ];
90
+ return parts.join("^NQ") + "^ORDERBYname";
91
+ };
92
+ // Execute queries in parallel, skipping based on type filter
93
+ const scopePromise = type === "plugin"
94
+ ? Promise.resolve(null)
95
+ : tableApi.get("sys_scope", {
96
+ sysparm_query: buildScopeQuery(),
97
+ sysparm_fields: "sys_id,name,scope,version,vendor,active,short_description,sys_class_name",
98
+ sysparm_limit: 25,
99
+ sysparm_display_value: "false",
100
+ });
101
+ const pluginPromise = type === "app"
102
+ ? Promise.resolve(null)
103
+ : tableApi.get("sys_plugins", {
104
+ sysparm_query: buildPluginQuery(),
105
+ sysparm_fields: "sys_id,name,id,version,active",
106
+ sysparm_limit: 25,
107
+ sysparm_display_value: "false",
108
+ });
109
+ const [scopeResp, pluginResp] = await Promise.all([
110
+ scopePromise,
111
+ pluginPromise,
112
+ ]);
113
+ // Check for retryable responses (stale session, no response)
114
+ if (scopeResp && isRetryableResponse(scopeResp)) {
115
+ const status = scopeResp?.status ?? "unknown";
116
+ throw new Error(`HTTP ${status} querying sys_scope`);
117
+ }
118
+ if (pluginResp && isRetryableResponse(pluginResp)) {
119
+ const status = pluginResp?.status ?? "unknown";
120
+ throw new Error(`HTTP ${status} querying sys_plugins`);
121
+ }
122
+ return { scopeResp, pluginResp };
123
+ });
124
+ const { scopeResp, pluginResp } = results;
125
+ // Check for non-retryable HTTP errors
126
+ if (scopeResp && scopeResp.status !== 200) {
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: `Error querying applications: HTTP ${scopeResp.status} ${scopeResp.statusText}`,
132
+ },
133
+ ],
134
+ isError: true,
135
+ };
136
+ }
137
+ if (pluginResp && pluginResp.status !== 200) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `Error querying plugins: HTTP ${pluginResp.status} ${pluginResp.statusText}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
148
+ const apps = scopeResp?.bodyObject?.result ?? [];
149
+ const plugins = pluginResp?.bodyObject?.result ?? [];
150
+ const totalFound = apps.length + plugins.length;
151
+ // Format output
152
+ const lines = [];
153
+ lines.push("=== Application & Plugin Search Results ===");
154
+ const searchInfo = [`Search: "${search_term}"`];
155
+ searchInfo.push(`Type: ${type}`);
156
+ if (active_only)
157
+ searchInfo.push("Active only: yes");
158
+ lines.push(searchInfo.join(" | "));
159
+ lines.push(`Found: ${totalFound} result(s)`);
160
+ // Applications section
161
+ if (type !== "plugin") {
162
+ lines.push("");
163
+ lines.push(`--- Applications (${apps.length}) ---`);
164
+ if (apps.length === 0) {
165
+ lines.push("No matching applications found.");
166
+ }
167
+ else {
168
+ apps.forEach((app, index) => {
169
+ const appType = classNameToLabel(app.sys_class_name);
170
+ lines.push("");
171
+ lines.push(`${index + 1}. ${app.name}`);
172
+ lines.push(` sys_id: ${app.sys_id}`);
173
+ lines.push(` Scope: ${app.scope}`);
174
+ lines.push(` Version: ${app.version || "N/A"}`);
175
+ lines.push(` Type: ${appType}`);
176
+ lines.push(` Active: ${app.active}`);
177
+ if (app.vendor)
178
+ lines.push(` Vendor: ${app.vendor}`);
179
+ if (app.short_description) {
180
+ const truncated = app.short_description.length > 120
181
+ ? app.short_description.substring(0, 120) + "..."
182
+ : app.short_description;
183
+ lines.push(` Description: ${truncated}`);
184
+ }
185
+ });
186
+ }
187
+ }
188
+ // Plugins section
189
+ if (type !== "app") {
190
+ lines.push("");
191
+ lines.push(`--- Plugins (${plugins.length}) ---`);
192
+ if (plugins.length === 0) {
193
+ lines.push("No matching plugins found.");
194
+ }
195
+ else {
196
+ plugins.forEach((plugin, index) => {
197
+ lines.push("");
198
+ lines.push(`${index + 1}. ${plugin.name}`);
199
+ lines.push(` sys_id: ${plugin.sys_id}`);
200
+ lines.push(` Plugin ID: ${plugin.id}`);
201
+ lines.push(` Version: ${plugin.version || "N/A"}`);
202
+ lines.push(` Active: ${plugin.active}`);
203
+ });
204
+ }
205
+ }
206
+ // Footer
207
+ lines.push("");
208
+ lines.push(`=== ${totalFound} result(s) found ===`);
209
+ if (apps.length > 0) {
210
+ lines.push("");
211
+ lines.push("Tip: Use an application's sys_id as the `scope` parameter in execute_script " +
212
+ "to run scripts within that application's scope.");
213
+ }
214
+ if (totalFound === 0) {
215
+ lines.push("");
216
+ lines.push("No applications or plugins matched your search. " +
217
+ "Try a shorter or different search term.");
218
+ }
219
+ return {
220
+ content: [
221
+ {
222
+ type: "text",
223
+ text: lines.join("\n"),
224
+ },
225
+ ],
226
+ };
227
+ }
228
+ catch (error) {
229
+ const message = error instanceof Error ? error.message : String(error);
230
+ return {
231
+ content: [
232
+ {
233
+ type: "text",
234
+ text: `Error looking up applications: ${message}`,
235
+ },
236
+ ],
237
+ isError: true,
238
+ };
239
+ }
240
+ });
241
+ }
242
+ //# sourceMappingURL=lookup-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-app.js","sourceRoot":"","sources":["../../src/tools/lookup-app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the lookup_columns tool on the MCP server.
4
+ *
5
+ * Searches sys_dictionary for columns on a specific table. Useful for
6
+ * validating column names and discovering available fields before
7
+ * building queries or scripts.
8
+ */
9
+ export declare function registerLookupColumnsTool(server: McpServer): void;
10
+ //# sourceMappingURL=lookup-columns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-columns.d.ts","sourceRoot":"","sources":["../../src/tools/lookup-columns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0CpE;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgMjE"}
@@ -0,0 +1,180 @@
1
+ import { z } from "zod";
2
+ import { TableAPIRequest } from "@sonisoft/now-sdk-ext-core";
3
+ import { withConnectionRetry, isRetryableResponse, } from "../common/connection.js";
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ /**
6
+ * Coerce any Table API field value to a plain string.
7
+ *
8
+ * With `sysparm_display_value=true`, non-reference fields come back as
9
+ * strings, but reference fields arrive as `{ display_value, link }`.
10
+ * This helper normalises both shapes to a string.
11
+ */
12
+ function str(field) {
13
+ if (field == null)
14
+ return "";
15
+ if (typeof field === "string")
16
+ return field;
17
+ if (typeof field === "object" && "display_value" in field) {
18
+ return String(field.display_value ?? "");
19
+ }
20
+ return String(field);
21
+ }
22
+ /**
23
+ * Registers the lookup_columns tool on the MCP server.
24
+ *
25
+ * Searches sys_dictionary for columns on a specific table. Useful for
26
+ * validating column names and discovering available fields before
27
+ * building queries or scripts.
28
+ */
29
+ export function registerLookupColumnsTool(server) {
30
+ server.registerTool("lookup_columns", {
31
+ title: "Lookup Table Columns",
32
+ description: "List or search columns (fields) on a ServiceNow table. Queries the sys_dictionary " +
33
+ "table to find column names, types, and metadata for a given table.\n\n" +
34
+ "Use this tool to:\n" +
35
+ "- List all columns on a table to see what fields are available\n" +
36
+ "- Validate a column name before using it in a query or script\n" +
37
+ "- Find the correct internal element name when you only know the display label\n" +
38
+ "- Check column types, whether a field is mandatory, read-only, or a reference\n\n" +
39
+ "Returns: element name (internal), column label (display), type, " +
40
+ "max length, reference target, mandatory/read-only/active flags.",
41
+ inputSchema: {
42
+ instance: z
43
+ .string()
44
+ .optional()
45
+ .describe("The ServiceNow instance auth alias (e.g., " +
46
+ '"dev224436", "prod"). If not provided, falls back ' +
47
+ "to the SN_AUTH_ALIAS environment variable."),
48
+ table: z
49
+ .string()
50
+ .describe("The internal table name to look up columns for (e.g., " +
51
+ '"incident", "cmdb_ci_server", "sys_user"). ' +
52
+ "Use lookup_table first if you are unsure of the exact table name."),
53
+ search_term: z
54
+ .string()
55
+ .optional()
56
+ .describe("Optional filter to search columns by element name or label. " +
57
+ "Case-insensitive partial matching (contains). " +
58
+ 'Examples: "assigned", "priority", "sys_created". ' +
59
+ "If omitted, returns all columns on the table."),
60
+ limit: z
61
+ .number()
62
+ .min(1)
63
+ .max(200)
64
+ .default(50)
65
+ .describe("Maximum number of columns to return. Default is 50, max is 200."),
66
+ },
67
+ }, async ({ instance, table, search_term, limit }) => {
68
+ try {
69
+ const response = await withConnectionRetry(instance, async (snInstance) => {
70
+ const tableApi = new TableAPIRequest(snInstance);
71
+ // Base filter: columns for this table, excluding the
72
+ // "collection" row which is the table definition itself.
73
+ const base = `name=${table}^internal_type!=collection`;
74
+ let query;
75
+ if (search_term) {
76
+ // ^NQ OR grouping: search by element name or column label
77
+ query =
78
+ `${base}^elementLIKE${search_term}` +
79
+ `^NQ${base}^column_labelLIKE${search_term}` +
80
+ `^ORDERBYelement`;
81
+ }
82
+ else {
83
+ query = `${base}^ORDERBYelement`;
84
+ }
85
+ const resp = await tableApi.get("sys_dictionary", {
86
+ sysparm_query: query,
87
+ sysparm_fields: "element,column_label,internal_type,max_length,reference,mandatory,active,read_only,default_value",
88
+ sysparm_limit: limit,
89
+ sysparm_display_value: "all",
90
+ });
91
+ if (isRetryableResponse(resp)) {
92
+ const status = resp?.status ?? "unknown";
93
+ throw new Error(`HTTP ${status} querying sys_dictionary`);
94
+ }
95
+ return resp;
96
+ });
97
+ if (response.status !== 200) {
98
+ return {
99
+ content: [
100
+ {
101
+ type: "text",
102
+ text: `Error querying columns: HTTP ${response.status} ${response.statusText}`,
103
+ },
104
+ ],
105
+ isError: true,
106
+ };
107
+ }
108
+ const columns = response.bodyObject?.result ?? [];
109
+ const lines = [];
110
+ lines.push(`=== Columns for table: ${table} ===`);
111
+ if (search_term) {
112
+ lines.push(`Search: "${search_term}"`);
113
+ }
114
+ lines.push(`Found: ${columns.length} column(s)`);
115
+ if (columns.length === 0) {
116
+ lines.push("");
117
+ if (search_term) {
118
+ lines.push(`No columns matching "${search_term}" found on table "${table}". ` +
119
+ "Try a shorter search term or omit it to see all columns.");
120
+ }
121
+ else {
122
+ lines.push(`No columns found for table "${table}". ` +
123
+ "Verify the table name is correct using lookup_table.");
124
+ }
125
+ }
126
+ else {
127
+ columns.forEach((col, index) => {
128
+ const element = str(col.element);
129
+ const label = str(col.column_label);
130
+ const type = str(col.internal_type);
131
+ const ref = str(col.reference);
132
+ const mandatory = str(col.mandatory);
133
+ const readOnly = str(col.read_only);
134
+ const active = str(col.active);
135
+ lines.push("");
136
+ lines.push(`${index + 1}. ${element}` + (label ? ` (${label})` : ""));
137
+ // Type line — include reference target when applicable
138
+ let typeLine = ` Type: ${type}`;
139
+ if (ref) {
140
+ typeLine += ` -> ${ref}`;
141
+ }
142
+ lines.push(typeLine);
143
+ lines.push(` Mandatory: ${mandatory || "false"} | ` +
144
+ `Read-only: ${readOnly || "false"} | ` +
145
+ `Active: ${active || "true"}`);
146
+ if (col.max_length) {
147
+ lines.push(` Max length: ${str(col.max_length)}`);
148
+ }
149
+ if (col.default_value) {
150
+ lines.push(` Default: ${str(col.default_value)}`);
151
+ }
152
+ });
153
+ lines.push("");
154
+ lines.push("Tip: Use column element names (left of parentheses) in encoded queries, " +
155
+ "GlideRecord scripts, and the fields parameter of query_table.");
156
+ }
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: lines.join("\n"),
162
+ },
163
+ ],
164
+ };
165
+ }
166
+ catch (error) {
167
+ const message = error instanceof Error ? error.message : String(error);
168
+ return {
169
+ content: [
170
+ {
171
+ type: "text",
172
+ text: `Error looking up columns: ${message}`,
173
+ },
174
+ ],
175
+ isError: true,
176
+ };
177
+ }
178
+ });
179
+ }
180
+ //# sourceMappingURL=lookup-columns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-columns.js","sourceRoot":"","sources":["../../src/tools/lookup-columns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the lookup_table tool on the MCP server.
4
+ *
5
+ * Searches sys_db_object (the ServiceNow table registry) by table name
6
+ * or label. Useful for validating table names before using them in
7
+ * query_table, execute_script, or other tools.
8
+ */
9
+ export declare function registerLookupTableTool(server: McpServer): void;
10
+ //# sourceMappingURL=lookup-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-table.d.ts","sourceRoot":"","sources":["../../src/tools/lookup-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwCpE;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyJ/D"}
@@ -0,0 +1,150 @@
1
+ import { z } from "zod";
2
+ import { TableAPIRequest } from "@sonisoft/now-sdk-ext-core";
3
+ import { withConnectionRetry, isRetryableResponse, } from "../common/connection.js";
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ /**
6
+ * Coerce any Table API field value to a plain string.
7
+ *
8
+ * With `sysparm_display_value=true`, non-reference fields come back as
9
+ * strings, but reference fields arrive as `{ display_value, link }`.
10
+ * This helper normalises both shapes to a string.
11
+ */
12
+ function str(field) {
13
+ if (field == null)
14
+ return "";
15
+ if (typeof field === "string")
16
+ return field;
17
+ if (typeof field === "object" && "display_value" in field) {
18
+ return String(field.display_value ?? "");
19
+ }
20
+ return String(field);
21
+ }
22
+ /**
23
+ * Registers the lookup_table tool on the MCP server.
24
+ *
25
+ * Searches sys_db_object (the ServiceNow table registry) by table name
26
+ * or label. Useful for validating table names before using them in
27
+ * query_table, execute_script, or other tools.
28
+ */
29
+ export function registerLookupTableTool(server) {
30
+ server.registerTool("lookup_table", {
31
+ title: "Lookup Table",
32
+ description: "Search for ServiceNow tables by name or label. Queries the sys_db_object table " +
33
+ "to find and validate table names.\n\n" +
34
+ "Use this tool to:\n" +
35
+ "- Verify a table name exists before using it with query_table or in GlideRecord scripts\n" +
36
+ "- Discover the correct internal name for a table when you only know the display label\n" +
37
+ "- Find related tables (e.g., search \"incident\" to see incident, incident_alert, etc.)\n" +
38
+ "- Check table hierarchy (which table a table extends)\n\n" +
39
+ "Returns: table name (internal), label (display), parent table, " +
40
+ "whether it is extendable, number prefix, and application scope.",
41
+ inputSchema: {
42
+ instance: z
43
+ .string()
44
+ .optional()
45
+ .describe("The ServiceNow instance auth alias (e.g., " +
46
+ '"dev224436", "prod"). If not provided, falls back ' +
47
+ "to the SN_AUTH_ALIAS environment variable."),
48
+ search_term: z
49
+ .string()
50
+ .describe("Table name or label to search for. Case-insensitive partial matching (contains). " +
51
+ 'Examples: "incident", "cmdb_ci", "Change Request".'),
52
+ limit: z
53
+ .number()
54
+ .min(1)
55
+ .max(100)
56
+ .default(25)
57
+ .describe("Maximum number of results to return. Default is 25, max is 100."),
58
+ },
59
+ }, async ({ instance, search_term, limit }) => {
60
+ try {
61
+ const response = await withConnectionRetry(instance, async (snInstance) => {
62
+ const tableApi = new TableAPIRequest(snInstance);
63
+ // ^NQ OR grouping: search by internal name or display label
64
+ const query = `nameLIKE${search_term}` +
65
+ `^NQlabelLIKE${search_term}` +
66
+ `^ORDERBYname`;
67
+ const resp = await tableApi.get("sys_db_object", {
68
+ sysparm_query: query,
69
+ sysparm_fields: "sys_id,name,label,super_class,is_extendable,number_ref,sys_scope",
70
+ sysparm_limit: limit,
71
+ sysparm_display_value: "all",
72
+ });
73
+ if (isRetryableResponse(resp)) {
74
+ const status = resp?.status ?? "unknown";
75
+ throw new Error(`HTTP ${status} querying sys_db_object`);
76
+ }
77
+ return resp;
78
+ });
79
+ if (response.status !== 200) {
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: `Error querying tables: HTTP ${response.status} ${response.statusText}`,
85
+ },
86
+ ],
87
+ isError: true,
88
+ };
89
+ }
90
+ const tables = response.bodyObject?.result ?? [];
91
+ const lines = [];
92
+ lines.push("=== Table Search Results ===");
93
+ lines.push(`Search: "${search_term}"`);
94
+ lines.push(`Found: ${tables.length} table(s)`);
95
+ if (tables.length === 0) {
96
+ lines.push("");
97
+ lines.push("No tables found matching your search. " +
98
+ "Try a shorter or different search term.");
99
+ }
100
+ else {
101
+ tables.forEach((table, index) => {
102
+ const name = str(table.name);
103
+ const label = str(table.label);
104
+ const sysId = str(table.sys_id);
105
+ const parent = str(table.super_class);
106
+ const extendable = str(table.is_extendable);
107
+ const numberRef = str(table.number_ref);
108
+ const scope = str(table.sys_scope);
109
+ lines.push("");
110
+ lines.push(`${index + 1}. ${name}` + (label ? ` (${label})` : ""));
111
+ lines.push(` sys_id: ${sysId}`);
112
+ if (parent) {
113
+ lines.push(` Extends: ${parent}`);
114
+ }
115
+ lines.push(` Extendable: ${extendable || "false"}`);
116
+ if (numberRef) {
117
+ lines.push(` Number prefix: ${numberRef}`);
118
+ }
119
+ if (scope) {
120
+ lines.push(` Scope: ${scope}`);
121
+ }
122
+ });
123
+ lines.push("");
124
+ lines.push("Tip: Use the table name (not label) with query_table or in GlideRecord scripts. " +
125
+ "Use lookup_columns to see the columns available on a table.");
126
+ }
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: lines.join("\n"),
132
+ },
133
+ ],
134
+ };
135
+ }
136
+ catch (error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `Error looking up tables: ${message}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
148
+ });
149
+ }
150
+ //# sourceMappingURL=lookup-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup-table.js","sourceRoot":"","sources":["../../src/tools/lookup-table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the query_update_records tool on the MCP server.
4
+ *
5
+ * Finds records matching an encoded query and updates them in bulk.
6
+ * Supports dry-run mode (confirm=false) to preview affected records before committing.
7
+ */
8
+ export declare function registerQueryUpdateRecordsTool(server: McpServer): void;
9
+ /**
10
+ * Registers the query_delete_records tool on the MCP server.
11
+ *
12
+ * Finds records matching an encoded query and deletes them in bulk.
13
+ * Supports dry-run mode (confirm=false) to preview affected records before committing.
14
+ */
15
+ export declare function registerQueryDeleteRecordsTool(server: McpServer): void;
16
+ //# sourceMappingURL=query-batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-batch.d.ts","sourceRoot":"","sources":["../../src/tools/query-batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmHtE;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8GtE"}