servicenow-mcp 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +16 -0
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/auth-browser.d.ts +21 -0
- package/dist/auth-browser.js +161 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +2759 -0
- package/package.json +57 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2759 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ServiceNow MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Comprehensive MCP for ServiceNow ITSM operations:
|
|
6
|
+
* - Incidents, Changes, Problems
|
|
7
|
+
* - Service Catalog & Requests
|
|
8
|
+
* - CMDB Configuration Items
|
|
9
|
+
* - Knowledge Base
|
|
10
|
+
* - Users, Groups, Approvals
|
|
11
|
+
*
|
|
12
|
+
* Supports:
|
|
13
|
+
* - Browser-based SSO authentication (recommended for enterprise)
|
|
14
|
+
* - REST Table API (basic auth)
|
|
15
|
+
* - GraphQL API (session-based)
|
|
16
|
+
*/
|
|
17
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
18
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
19
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
20
|
+
import { loadCookies, authenticateViaBrowser } from "./auth-browser.js";
|
|
21
|
+
// Configuration from environment
|
|
22
|
+
const INSTANCE_URL = process.env.SERVICENOW_INSTANCE_URL || "";
|
|
23
|
+
const USERNAME = process.env.SERVICENOW_USERNAME || "";
|
|
24
|
+
const PASSWORD = process.env.SERVICENOW_PASSWORD || "";
|
|
25
|
+
const SESSION_TOKEN = process.env.SERVICENOW_SESSION_TOKEN || "";
|
|
26
|
+
const USER_TOKEN = process.env.SERVICENOW_USER_TOKEN || "";
|
|
27
|
+
// Load browser auth cookies if available (mutable to allow hot-reload)
|
|
28
|
+
let browserAuth = loadCookies();
|
|
29
|
+
// Function to reload cookies without restarting the server
|
|
30
|
+
function reloadBrowserAuth() {
|
|
31
|
+
const newAuth = loadCookies();
|
|
32
|
+
if (newAuth) {
|
|
33
|
+
browserAuth = newAuth;
|
|
34
|
+
console.error("✅ Browser auth cookies reloaded successfully");
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
console.error("❌ Failed to reload browser auth cookies");
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
// HTTP client with connection pooling
|
|
41
|
+
import { Agent } from "node:https";
|
|
42
|
+
const httpsAgent = new Agent({ keepAlive: true, maxSockets: 10 });
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Tool Definitions
|
|
45
|
+
// ============================================================================
|
|
46
|
+
const TOOLS = [
|
|
47
|
+
// -------------------------------------------------------------------------
|
|
48
|
+
// AUTHENTICATION
|
|
49
|
+
// -------------------------------------------------------------------------
|
|
50
|
+
{
|
|
51
|
+
name: "auth_browser",
|
|
52
|
+
description: "Launch browser for SSO authentication. Opens a browser window where you can log in with your enterprise SSO credentials. Cookies are captured and saved for subsequent API calls. Use this when you don't have API keys and need to use SSO.",
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties: {
|
|
56
|
+
instance_url: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "ServiceNow instance URL (e.g., https://mycompany.service-now.com). If not provided, uses SERVICENOW_INSTANCE_URL env var.",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "auth_status",
|
|
65
|
+
description: "Check current authentication status. Shows which auth method is configured and whether credentials/cookies are valid.",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
// -------------------------------------------------------------------------
|
|
72
|
+
// UNIFIED WORK QUEUE (Priority tools for finding actionable items)
|
|
73
|
+
// -------------------------------------------------------------------------
|
|
74
|
+
{
|
|
75
|
+
name: "my_context",
|
|
76
|
+
description: "Get current user's identity, groups, and roles. Returns cached user info including sys_id, name, email, department, group memberships, and roles. Use this first to understand who you're working as.",
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "my_work_queue",
|
|
84
|
+
description: "Get ALL actionable items for current user in a single call: assigned tasks, pending approvals, and unassigned group queue items. This is the recommended first tool to use when user asks 'what do I need to work on?' or 'what are my open tasks?'",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
include: {
|
|
89
|
+
type: "array",
|
|
90
|
+
items: {
|
|
91
|
+
type: "string",
|
|
92
|
+
enum: ["assigned", "approvals", "group_queue"],
|
|
93
|
+
},
|
|
94
|
+
description: "Which categories to include (default: all three)",
|
|
95
|
+
default: ["assigned", "approvals", "group_queue"],
|
|
96
|
+
},
|
|
97
|
+
keyword: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "Filter results by keyword in short_description (e.g., 'firewall', 'SAP')",
|
|
100
|
+
},
|
|
101
|
+
limit: {
|
|
102
|
+
type: "number",
|
|
103
|
+
description: "Max results per category (default 20)",
|
|
104
|
+
default: 20,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
// -------------------------------------------------------------------------
|
|
110
|
+
// INCIDENTS
|
|
111
|
+
// -------------------------------------------------------------------------
|
|
112
|
+
{
|
|
113
|
+
name: "incidents_list",
|
|
114
|
+
description: "List incidents with optional filtering. Returns incident number, short description, state, priority, assigned_to.",
|
|
115
|
+
inputSchema: {
|
|
116
|
+
type: "object",
|
|
117
|
+
properties: {
|
|
118
|
+
query: {
|
|
119
|
+
type: "string",
|
|
120
|
+
description: "ServiceNow encoded query (e.g., 'state=1^priority=1' for new P1s)",
|
|
121
|
+
},
|
|
122
|
+
limit: {
|
|
123
|
+
type: "number",
|
|
124
|
+
description: "Max results (default 20)",
|
|
125
|
+
default: 20,
|
|
126
|
+
},
|
|
127
|
+
offset: {
|
|
128
|
+
type: "number",
|
|
129
|
+
description: "Pagination offset",
|
|
130
|
+
default: 0,
|
|
131
|
+
},
|
|
132
|
+
fields: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "Comma-separated fields to return",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "incidents_get",
|
|
141
|
+
description: "Get a single incident by sys_id or number",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {
|
|
145
|
+
id: {
|
|
146
|
+
type: "string",
|
|
147
|
+
description: "Incident sys_id or number (e.g., INC0012345)",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
required: ["id"],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "incidents_create",
|
|
155
|
+
description: "Create a new incident",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties: {
|
|
159
|
+
short_description: {
|
|
160
|
+
type: "string",
|
|
161
|
+
description: "Brief description of the issue",
|
|
162
|
+
},
|
|
163
|
+
description: { type: "string", description: "Detailed description" },
|
|
164
|
+
caller_id: {
|
|
165
|
+
type: "string",
|
|
166
|
+
description: "User sys_id or email of the caller",
|
|
167
|
+
},
|
|
168
|
+
category: { type: "string", description: "Incident category" },
|
|
169
|
+
subcategory: { type: "string", description: "Incident subcategory" },
|
|
170
|
+
priority: { type: "number", description: "Priority 1-5 (1=Critical)" },
|
|
171
|
+
assignment_group: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Assignment group sys_id or name",
|
|
174
|
+
},
|
|
175
|
+
cmdb_ci: { type: "string", description: "Configuration item sys_id" },
|
|
176
|
+
},
|
|
177
|
+
required: ["short_description"],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "incidents_update",
|
|
182
|
+
description: "Update an existing incident",
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: "object",
|
|
185
|
+
properties: {
|
|
186
|
+
id: { type: "string", description: "Incident sys_id or number" },
|
|
187
|
+
data: {
|
|
188
|
+
type: "object",
|
|
189
|
+
description: "Fields to update (state, priority, assigned_to, work_notes, etc.)",
|
|
190
|
+
additionalProperties: true,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
required: ["id", "data"],
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "incidents_add_comment",
|
|
198
|
+
description: "Add a work note or comment to an incident",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
properties: {
|
|
202
|
+
id: { type: "string", description: "Incident sys_id or number" },
|
|
203
|
+
comment: { type: "string", description: "The comment/work note text" },
|
|
204
|
+
type: {
|
|
205
|
+
type: "string",
|
|
206
|
+
enum: ["work_notes", "comments"],
|
|
207
|
+
description: "work_notes (internal) or comments (customer visible)",
|
|
208
|
+
default: "work_notes",
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
required: ["id", "comment"],
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "incidents_resolve",
|
|
216
|
+
description: "Resolve an incident",
|
|
217
|
+
inputSchema: {
|
|
218
|
+
type: "object",
|
|
219
|
+
properties: {
|
|
220
|
+
id: { type: "string", description: "Incident sys_id or number" },
|
|
221
|
+
resolution_code: { type: "string", description: "Resolution code" },
|
|
222
|
+
resolution_notes: {
|
|
223
|
+
type: "string",
|
|
224
|
+
description: "Resolution notes/close notes",
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
required: ["id", "resolution_notes"],
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
// -------------------------------------------------------------------------
|
|
231
|
+
// CHANGE REQUESTS
|
|
232
|
+
// -------------------------------------------------------------------------
|
|
233
|
+
{
|
|
234
|
+
name: "changes_list",
|
|
235
|
+
description: "List change requests with optional filtering",
|
|
236
|
+
inputSchema: {
|
|
237
|
+
type: "object",
|
|
238
|
+
properties: {
|
|
239
|
+
query: { type: "string", description: "ServiceNow encoded query" },
|
|
240
|
+
limit: { type: "number", default: 20 },
|
|
241
|
+
offset: { type: "number", default: 0 },
|
|
242
|
+
type: {
|
|
243
|
+
type: "string",
|
|
244
|
+
enum: ["standard", "normal", "emergency"],
|
|
245
|
+
description: "Filter by change type",
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: "changes_get",
|
|
252
|
+
description: "Get a single change request by sys_id or number",
|
|
253
|
+
inputSchema: {
|
|
254
|
+
type: "object",
|
|
255
|
+
properties: {
|
|
256
|
+
id: {
|
|
257
|
+
type: "string",
|
|
258
|
+
description: "Change request sys_id or number (e.g., CHG0012345)",
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
required: ["id"],
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "changes_create",
|
|
266
|
+
description: "Create a new change request",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
short_description: { type: "string" },
|
|
271
|
+
description: { type: "string" },
|
|
272
|
+
type: { type: "string", enum: ["standard", "normal", "emergency"] },
|
|
273
|
+
category: { type: "string" },
|
|
274
|
+
assignment_group: { type: "string" },
|
|
275
|
+
cmdb_ci: { type: "string" },
|
|
276
|
+
start_date: {
|
|
277
|
+
type: "string",
|
|
278
|
+
description: "Planned start (ISO format)",
|
|
279
|
+
},
|
|
280
|
+
end_date: { type: "string", description: "Planned end (ISO format)" },
|
|
281
|
+
justification: { type: "string" },
|
|
282
|
+
implementation_plan: { type: "string" },
|
|
283
|
+
backout_plan: { type: "string" },
|
|
284
|
+
test_plan: { type: "string" },
|
|
285
|
+
},
|
|
286
|
+
required: ["short_description", "type"],
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "changes_tasks",
|
|
291
|
+
description: "Get tasks associated with a change request",
|
|
292
|
+
inputSchema: {
|
|
293
|
+
type: "object",
|
|
294
|
+
properties: {
|
|
295
|
+
id: { type: "string", description: "Change request sys_id or number" },
|
|
296
|
+
},
|
|
297
|
+
required: ["id"],
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
// -------------------------------------------------------------------------
|
|
301
|
+
// SERVICE CATALOG
|
|
302
|
+
// -------------------------------------------------------------------------
|
|
303
|
+
{
|
|
304
|
+
name: "catalog_items",
|
|
305
|
+
description: "List available service catalog items",
|
|
306
|
+
inputSchema: {
|
|
307
|
+
type: "object",
|
|
308
|
+
properties: {
|
|
309
|
+
category: {
|
|
310
|
+
type: "string",
|
|
311
|
+
description: "Filter by category sys_id or name",
|
|
312
|
+
},
|
|
313
|
+
query: { type: "string", description: "Search text" },
|
|
314
|
+
limit: { type: "number", default: 20 },
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: "catalog_get",
|
|
320
|
+
description: "Get details of a catalog item including variables/questions",
|
|
321
|
+
inputSchema: {
|
|
322
|
+
type: "object",
|
|
323
|
+
properties: {
|
|
324
|
+
id: { type: "string", description: "Catalog item sys_id" },
|
|
325
|
+
},
|
|
326
|
+
required: ["id"],
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: "catalog_order",
|
|
331
|
+
description: "Order/submit a catalog item request",
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: "object",
|
|
334
|
+
properties: {
|
|
335
|
+
item_id: { type: "string", description: "Catalog item sys_id" },
|
|
336
|
+
variables: {
|
|
337
|
+
type: "object",
|
|
338
|
+
description: "Variable values for the request",
|
|
339
|
+
additionalProperties: true,
|
|
340
|
+
},
|
|
341
|
+
requested_for: {
|
|
342
|
+
type: "string",
|
|
343
|
+
description: "User sys_id (defaults to current user)",
|
|
344
|
+
},
|
|
345
|
+
quantity: { type: "number", default: 1 },
|
|
346
|
+
},
|
|
347
|
+
required: ["item_id"],
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: "requests_list",
|
|
352
|
+
description: "List service requests (sc_request) for current user or with filter",
|
|
353
|
+
inputSchema: {
|
|
354
|
+
type: "object",
|
|
355
|
+
properties: {
|
|
356
|
+
query: { type: "string" },
|
|
357
|
+
limit: { type: "number", default: 20 },
|
|
358
|
+
my_requests: {
|
|
359
|
+
type: "boolean",
|
|
360
|
+
description: "Only show my requests",
|
|
361
|
+
default: true,
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: "requests_items",
|
|
368
|
+
description: "List requested items (sc_req_item) with status",
|
|
369
|
+
inputSchema: {
|
|
370
|
+
type: "object",
|
|
371
|
+
properties: {
|
|
372
|
+
query: { type: "string" },
|
|
373
|
+
limit: { type: "number", default: 20 },
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
// -------------------------------------------------------------------------
|
|
378
|
+
// CMDB
|
|
379
|
+
// -------------------------------------------------------------------------
|
|
380
|
+
{
|
|
381
|
+
name: "cmdb_search",
|
|
382
|
+
description: "Search CMDB configuration items",
|
|
383
|
+
inputSchema: {
|
|
384
|
+
type: "object",
|
|
385
|
+
properties: {
|
|
386
|
+
query: { type: "string", description: "Search text or encoded query" },
|
|
387
|
+
class: {
|
|
388
|
+
type: "string",
|
|
389
|
+
description: "CI class (cmdb_ci_server, cmdb_ci_app, etc.)",
|
|
390
|
+
default: "cmdb_ci",
|
|
391
|
+
},
|
|
392
|
+
limit: { type: "number", default: 20 },
|
|
393
|
+
},
|
|
394
|
+
required: ["query"],
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
name: "cmdb_get",
|
|
399
|
+
description: "Get configuration item details",
|
|
400
|
+
inputSchema: {
|
|
401
|
+
type: "object",
|
|
402
|
+
properties: {
|
|
403
|
+
id: { type: "string", description: "CI sys_id or name" },
|
|
404
|
+
class: {
|
|
405
|
+
type: "string",
|
|
406
|
+
description: "CI class table",
|
|
407
|
+
default: "cmdb_ci",
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
required: ["id"],
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: "cmdb_relationships",
|
|
415
|
+
description: "Get relationships for a configuration item",
|
|
416
|
+
inputSchema: {
|
|
417
|
+
type: "object",
|
|
418
|
+
properties: {
|
|
419
|
+
id: { type: "string", description: "CI sys_id" },
|
|
420
|
+
direction: {
|
|
421
|
+
type: "string",
|
|
422
|
+
enum: ["parent", "child", "both"],
|
|
423
|
+
default: "both",
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
required: ["id"],
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
// -------------------------------------------------------------------------
|
|
430
|
+
// PROBLEMS
|
|
431
|
+
// -------------------------------------------------------------------------
|
|
432
|
+
{
|
|
433
|
+
name: "problems_list",
|
|
434
|
+
description: "List problem records",
|
|
435
|
+
inputSchema: {
|
|
436
|
+
type: "object",
|
|
437
|
+
properties: {
|
|
438
|
+
query: { type: "string" },
|
|
439
|
+
limit: { type: "number", default: 20 },
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: "problems_get",
|
|
445
|
+
description: "Get a problem record",
|
|
446
|
+
inputSchema: {
|
|
447
|
+
type: "object",
|
|
448
|
+
properties: {
|
|
449
|
+
id: { type: "string", description: "Problem sys_id or number" },
|
|
450
|
+
},
|
|
451
|
+
required: ["id"],
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
name: "problems_create",
|
|
456
|
+
description: "Create a problem record",
|
|
457
|
+
inputSchema: {
|
|
458
|
+
type: "object",
|
|
459
|
+
properties: {
|
|
460
|
+
short_description: { type: "string" },
|
|
461
|
+
description: { type: "string" },
|
|
462
|
+
category: { type: "string" },
|
|
463
|
+
subcategory: { type: "string" },
|
|
464
|
+
assignment_group: { type: "string" },
|
|
465
|
+
cmdb_ci: { type: "string" },
|
|
466
|
+
},
|
|
467
|
+
required: ["short_description"],
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
// -------------------------------------------------------------------------
|
|
471
|
+
// KNOWLEDGE
|
|
472
|
+
// -------------------------------------------------------------------------
|
|
473
|
+
{
|
|
474
|
+
name: "knowledge_search",
|
|
475
|
+
description: "Search knowledge base articles",
|
|
476
|
+
inputSchema: {
|
|
477
|
+
type: "object",
|
|
478
|
+
properties: {
|
|
479
|
+
query: { type: "string", description: "Search text" },
|
|
480
|
+
knowledge_base: {
|
|
481
|
+
type: "string",
|
|
482
|
+
description: "KB sys_id to search in",
|
|
483
|
+
},
|
|
484
|
+
limit: { type: "number", default: 10 },
|
|
485
|
+
},
|
|
486
|
+
required: ["query"],
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
name: "knowledge_get",
|
|
491
|
+
description: "Get a knowledge article",
|
|
492
|
+
inputSchema: {
|
|
493
|
+
type: "object",
|
|
494
|
+
properties: {
|
|
495
|
+
id: { type: "string", description: "Article sys_id or number" },
|
|
496
|
+
},
|
|
497
|
+
required: ["id"],
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
// -------------------------------------------------------------------------
|
|
501
|
+
// USERS & GROUPS
|
|
502
|
+
// -------------------------------------------------------------------------
|
|
503
|
+
{
|
|
504
|
+
name: "users_search",
|
|
505
|
+
description: "Search for users",
|
|
506
|
+
inputSchema: {
|
|
507
|
+
type: "object",
|
|
508
|
+
properties: {
|
|
509
|
+
query: {
|
|
510
|
+
type: "string",
|
|
511
|
+
description: "Name, email, or user_name to search",
|
|
512
|
+
},
|
|
513
|
+
limit: { type: "number", default: 10 },
|
|
514
|
+
},
|
|
515
|
+
required: ["query"],
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
name: "users_get",
|
|
520
|
+
description: "Get user details",
|
|
521
|
+
inputSchema: {
|
|
522
|
+
type: "object",
|
|
523
|
+
properties: {
|
|
524
|
+
id: { type: "string", description: "User sys_id, user_name, or email" },
|
|
525
|
+
},
|
|
526
|
+
required: ["id"],
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
name: "groups_list",
|
|
531
|
+
description: "List groups",
|
|
532
|
+
inputSchema: {
|
|
533
|
+
type: "object",
|
|
534
|
+
properties: {
|
|
535
|
+
query: { type: "string", description: "Filter by name" },
|
|
536
|
+
type: { type: "string", description: "Group type" },
|
|
537
|
+
limit: { type: "number", default: 20 },
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: "groups_members",
|
|
543
|
+
description: "Get members of a group",
|
|
544
|
+
inputSchema: {
|
|
545
|
+
type: "object",
|
|
546
|
+
properties: {
|
|
547
|
+
id: { type: "string", description: "Group sys_id or name" },
|
|
548
|
+
},
|
|
549
|
+
required: ["id"],
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
// -------------------------------------------------------------------------
|
|
553
|
+
// TASKS & APPROVALS
|
|
554
|
+
// -------------------------------------------------------------------------
|
|
555
|
+
{
|
|
556
|
+
name: "tasks_my_tasks",
|
|
557
|
+
description: "Get tasks assigned to current user",
|
|
558
|
+
inputSchema: {
|
|
559
|
+
type: "object",
|
|
560
|
+
properties: {
|
|
561
|
+
state: {
|
|
562
|
+
type: "string",
|
|
563
|
+
description: "Filter by state (e.g., 'open', 'pending')",
|
|
564
|
+
},
|
|
565
|
+
limit: { type: "number", default: 20 },
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
name: "tasks_update",
|
|
571
|
+
description: "Update a task",
|
|
572
|
+
inputSchema: {
|
|
573
|
+
type: "object",
|
|
574
|
+
properties: {
|
|
575
|
+
id: { type: "string", description: "Task sys_id or number" },
|
|
576
|
+
data: { type: "object", additionalProperties: true },
|
|
577
|
+
},
|
|
578
|
+
required: ["id", "data"],
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
name: "approvals_pending",
|
|
583
|
+
description: "Get pending approvals for current user with ENRICHED details from parent records. Returns number, short_description, opened_by, urgency, and stage - not just approval metadata. Supports keyword filtering.",
|
|
584
|
+
inputSchema: {
|
|
585
|
+
type: "object",
|
|
586
|
+
properties: {
|
|
587
|
+
keyword: {
|
|
588
|
+
type: "string",
|
|
589
|
+
description: "Filter by keyword in parent record's short_description (e.g., 'firewall', 'access')",
|
|
590
|
+
},
|
|
591
|
+
type: {
|
|
592
|
+
type: "string",
|
|
593
|
+
enum: ["all", "sc_req_item", "change_request", "sc_task"],
|
|
594
|
+
description: "Filter by parent record type",
|
|
595
|
+
default: "all",
|
|
596
|
+
},
|
|
597
|
+
limit: { type: "number", default: 20 },
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
name: "approvals_approve",
|
|
603
|
+
description: "Approve an approval request",
|
|
604
|
+
inputSchema: {
|
|
605
|
+
type: "object",
|
|
606
|
+
properties: {
|
|
607
|
+
id: { type: "string", description: "Approval sys_id" },
|
|
608
|
+
comments: { type: "string", description: "Approval comments" },
|
|
609
|
+
},
|
|
610
|
+
required: ["id"],
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
name: "approvals_reject",
|
|
615
|
+
description: "Reject an approval request",
|
|
616
|
+
inputSchema: {
|
|
617
|
+
type: "object",
|
|
618
|
+
properties: {
|
|
619
|
+
id: { type: "string", description: "Approval sys_id" },
|
|
620
|
+
comments: { type: "string", description: "Rejection reason" },
|
|
621
|
+
},
|
|
622
|
+
required: ["id", "comments"],
|
|
623
|
+
},
|
|
624
|
+
},
|
|
625
|
+
// -------------------------------------------------------------------------
|
|
626
|
+
// ATTACHMENTS (Full API)
|
|
627
|
+
// -------------------------------------------------------------------------
|
|
628
|
+
{
|
|
629
|
+
name: "attachment_list",
|
|
630
|
+
description: "List attachments for a record",
|
|
631
|
+
inputSchema: {
|
|
632
|
+
type: "object",
|
|
633
|
+
properties: {
|
|
634
|
+
table: { type: "string", description: "Table name" },
|
|
635
|
+
id: { type: "string", description: "Record sys_id" },
|
|
636
|
+
},
|
|
637
|
+
required: ["table", "id"],
|
|
638
|
+
},
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
name: "attachment_get",
|
|
642
|
+
description: "Get attachment metadata by sys_id",
|
|
643
|
+
inputSchema: {
|
|
644
|
+
type: "object",
|
|
645
|
+
properties: {
|
|
646
|
+
id: { type: "string", description: "Attachment sys_id" },
|
|
647
|
+
},
|
|
648
|
+
required: ["id"],
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
name: "attachment_download",
|
|
653
|
+
description: "Get attachment content (returns base64 encoded for binary files)",
|
|
654
|
+
inputSchema: {
|
|
655
|
+
type: "object",
|
|
656
|
+
properties: {
|
|
657
|
+
id: { type: "string", description: "Attachment sys_id" },
|
|
658
|
+
},
|
|
659
|
+
required: ["id"],
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
name: "attachment_upload",
|
|
664
|
+
description: "Upload an attachment to a record",
|
|
665
|
+
inputSchema: {
|
|
666
|
+
type: "object",
|
|
667
|
+
properties: {
|
|
668
|
+
table: { type: "string", description: "Target table name" },
|
|
669
|
+
id: { type: "string", description: "Target record sys_id" },
|
|
670
|
+
filename: { type: "string", description: "File name" },
|
|
671
|
+
content: {
|
|
672
|
+
type: "string",
|
|
673
|
+
description: "Base64 encoded file content",
|
|
674
|
+
},
|
|
675
|
+
content_type: {
|
|
676
|
+
type: "string",
|
|
677
|
+
description: "MIME type (e.g., application/pdf)",
|
|
678
|
+
default: "application/octet-stream",
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
required: ["table", "id", "filename", "content"],
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
name: "attachment_delete",
|
|
686
|
+
description: "Delete an attachment",
|
|
687
|
+
inputSchema: {
|
|
688
|
+
type: "object",
|
|
689
|
+
properties: {
|
|
690
|
+
id: { type: "string", description: "Attachment sys_id" },
|
|
691
|
+
},
|
|
692
|
+
required: ["id"],
|
|
693
|
+
},
|
|
694
|
+
},
|
|
695
|
+
// -------------------------------------------------------------------------
|
|
696
|
+
// SERVICE CATALOG (Full sn_sc API)
|
|
697
|
+
// -------------------------------------------------------------------------
|
|
698
|
+
{
|
|
699
|
+
name: "catalog_categories",
|
|
700
|
+
description: "List service catalog categories",
|
|
701
|
+
inputSchema: {
|
|
702
|
+
type: "object",
|
|
703
|
+
properties: {
|
|
704
|
+
catalog_id: {
|
|
705
|
+
type: "string",
|
|
706
|
+
description: "Catalog sys_id (optional)",
|
|
707
|
+
},
|
|
708
|
+
limit: { type: "number", default: 50 },
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
name: "catalog_item_variables",
|
|
714
|
+
description: "Get variables/questions for a catalog item (required fields for ordering)",
|
|
715
|
+
inputSchema: {
|
|
716
|
+
type: "object",
|
|
717
|
+
properties: {
|
|
718
|
+
id: { type: "string", description: "Catalog item sys_id" },
|
|
719
|
+
},
|
|
720
|
+
required: ["id"],
|
|
721
|
+
},
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
name: "catalog_add_to_cart",
|
|
725
|
+
description: "Add a catalog item to the shopping cart",
|
|
726
|
+
inputSchema: {
|
|
727
|
+
type: "object",
|
|
728
|
+
properties: {
|
|
729
|
+
item_id: { type: "string", description: "Catalog item sys_id" },
|
|
730
|
+
quantity: { type: "number", default: 1 },
|
|
731
|
+
variables: {
|
|
732
|
+
type: "object",
|
|
733
|
+
description: "Variable values for the item",
|
|
734
|
+
additionalProperties: true,
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
required: ["item_id"],
|
|
738
|
+
},
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
name: "catalog_get_cart",
|
|
742
|
+
description: "Get current shopping cart contents",
|
|
743
|
+
inputSchema: {
|
|
744
|
+
type: "object",
|
|
745
|
+
properties: {},
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
name: "catalog_submit_cart",
|
|
750
|
+
description: "Submit/checkout the shopping cart to create requests",
|
|
751
|
+
inputSchema: {
|
|
752
|
+
type: "object",
|
|
753
|
+
properties: {},
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
name: "catalog_order_now",
|
|
758
|
+
description: "Order a catalog item immediately (skip cart, single-step order)",
|
|
759
|
+
inputSchema: {
|
|
760
|
+
type: "object",
|
|
761
|
+
properties: {
|
|
762
|
+
item_id: { type: "string", description: "Catalog item sys_id" },
|
|
763
|
+
quantity: { type: "number", default: 1 },
|
|
764
|
+
variables: {
|
|
765
|
+
type: "object",
|
|
766
|
+
description: "Variable values for the item",
|
|
767
|
+
additionalProperties: true,
|
|
768
|
+
},
|
|
769
|
+
requested_for: {
|
|
770
|
+
type: "string",
|
|
771
|
+
description: "User sys_id to request for",
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
required: ["item_id"],
|
|
775
|
+
},
|
|
776
|
+
},
|
|
777
|
+
// -------------------------------------------------------------------------
|
|
778
|
+
// IMPORT SET API
|
|
779
|
+
// -------------------------------------------------------------------------
|
|
780
|
+
{
|
|
781
|
+
name: "import_set_load",
|
|
782
|
+
description: "Load data into an import set staging table",
|
|
783
|
+
inputSchema: {
|
|
784
|
+
type: "object",
|
|
785
|
+
properties: {
|
|
786
|
+
table: {
|
|
787
|
+
type: "string",
|
|
788
|
+
description: "Import set table name (e.g., u_my_import_set)",
|
|
789
|
+
},
|
|
790
|
+
data: {
|
|
791
|
+
type: "object",
|
|
792
|
+
description: "Data to import (single record)",
|
|
793
|
+
additionalProperties: true,
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
required: ["table", "data"],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: "import_set_load_multiple",
|
|
801
|
+
description: "Load multiple records into an import set staging table",
|
|
802
|
+
inputSchema: {
|
|
803
|
+
type: "object",
|
|
804
|
+
properties: {
|
|
805
|
+
table: {
|
|
806
|
+
type: "string",
|
|
807
|
+
description: "Import set table name",
|
|
808
|
+
},
|
|
809
|
+
records: {
|
|
810
|
+
type: "array",
|
|
811
|
+
items: { type: "object" },
|
|
812
|
+
description: "Array of records to import",
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
required: ["table", "records"],
|
|
816
|
+
},
|
|
817
|
+
},
|
|
818
|
+
{
|
|
819
|
+
name: "import_set_status",
|
|
820
|
+
description: "Get status of an import set",
|
|
821
|
+
inputSchema: {
|
|
822
|
+
type: "object",
|
|
823
|
+
properties: {
|
|
824
|
+
id: { type: "string", description: "Import set sys_id" },
|
|
825
|
+
},
|
|
826
|
+
required: ["id"],
|
|
827
|
+
},
|
|
828
|
+
},
|
|
829
|
+
// -------------------------------------------------------------------------
|
|
830
|
+
// BATCH API
|
|
831
|
+
// -------------------------------------------------------------------------
|
|
832
|
+
{
|
|
833
|
+
name: "batch_request",
|
|
834
|
+
description: "Execute multiple API requests in a single call",
|
|
835
|
+
inputSchema: {
|
|
836
|
+
type: "object",
|
|
837
|
+
properties: {
|
|
838
|
+
requests: {
|
|
839
|
+
type: "array",
|
|
840
|
+
description: "Array of request objects",
|
|
841
|
+
items: {
|
|
842
|
+
type: "object",
|
|
843
|
+
properties: {
|
|
844
|
+
id: { type: "string", description: "Request identifier" },
|
|
845
|
+
method: {
|
|
846
|
+
type: "string",
|
|
847
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
848
|
+
},
|
|
849
|
+
url: { type: "string", description: "Relative URL path" },
|
|
850
|
+
body: {
|
|
851
|
+
type: "object",
|
|
852
|
+
description: "Request body for POST/PUT",
|
|
853
|
+
},
|
|
854
|
+
headers: { type: "object", description: "Additional headers" },
|
|
855
|
+
},
|
|
856
|
+
required: ["id", "method", "url"],
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
},
|
|
860
|
+
required: ["requests"],
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
// -------------------------------------------------------------------------
|
|
864
|
+
// CMDB INSTANCE API (Advanced)
|
|
865
|
+
// -------------------------------------------------------------------------
|
|
866
|
+
{
|
|
867
|
+
name: "cmdb_classes",
|
|
868
|
+
description: "List CMDB CI classes/types",
|
|
869
|
+
inputSchema: {
|
|
870
|
+
type: "object",
|
|
871
|
+
properties: {
|
|
872
|
+
parent_class: {
|
|
873
|
+
type: "string",
|
|
874
|
+
description: "Parent class to filter by",
|
|
875
|
+
default: "cmdb_ci",
|
|
876
|
+
},
|
|
877
|
+
limit: { type: "number", default: 50 },
|
|
878
|
+
},
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
name: "cmdb_instance_list",
|
|
883
|
+
description: "List CMDB instances by class (uses CMDB Instance API /now/cmdb/instance)",
|
|
884
|
+
inputSchema: {
|
|
885
|
+
type: "object",
|
|
886
|
+
properties: {
|
|
887
|
+
class_name: {
|
|
888
|
+
type: "string",
|
|
889
|
+
description: "CI class name (e.g., cmdb_ci_server, cmdb_ci_linux_server)",
|
|
890
|
+
},
|
|
891
|
+
query: { type: "string", description: "Filter query" },
|
|
892
|
+
limit: { type: "number", default: 20 },
|
|
893
|
+
},
|
|
894
|
+
required: ["class_name"],
|
|
895
|
+
},
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
name: "cmdb_create",
|
|
899
|
+
description: "Create a new CMDB configuration item",
|
|
900
|
+
inputSchema: {
|
|
901
|
+
type: "object",
|
|
902
|
+
properties: {
|
|
903
|
+
class_name: {
|
|
904
|
+
type: "string",
|
|
905
|
+
description: "CI class (e.g., cmdb_ci_server)",
|
|
906
|
+
},
|
|
907
|
+
data: {
|
|
908
|
+
type: "object",
|
|
909
|
+
description: "CI attributes",
|
|
910
|
+
additionalProperties: true,
|
|
911
|
+
},
|
|
912
|
+
},
|
|
913
|
+
required: ["class_name", "data"],
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
name: "cmdb_update",
|
|
918
|
+
description: "Update a CMDB configuration item",
|
|
919
|
+
inputSchema: {
|
|
920
|
+
type: "object",
|
|
921
|
+
properties: {
|
|
922
|
+
id: { type: "string", description: "CI sys_id" },
|
|
923
|
+
class_name: { type: "string", description: "CI class" },
|
|
924
|
+
data: { type: "object", additionalProperties: true },
|
|
925
|
+
},
|
|
926
|
+
required: ["id", "data"],
|
|
927
|
+
},
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
name: "cmdb_relationship_create",
|
|
931
|
+
description: "Create a relationship between two CIs",
|
|
932
|
+
inputSchema: {
|
|
933
|
+
type: "object",
|
|
934
|
+
properties: {
|
|
935
|
+
parent: { type: "string", description: "Parent CI sys_id" },
|
|
936
|
+
child: { type: "string", description: "Child CI sys_id" },
|
|
937
|
+
type: {
|
|
938
|
+
type: "string",
|
|
939
|
+
description: "Relationship type sys_id or name",
|
|
940
|
+
},
|
|
941
|
+
},
|
|
942
|
+
required: ["parent", "child", "type"],
|
|
943
|
+
},
|
|
944
|
+
},
|
|
945
|
+
// -------------------------------------------------------------------------
|
|
946
|
+
// TASK SLA
|
|
947
|
+
// -------------------------------------------------------------------------
|
|
948
|
+
{
|
|
949
|
+
name: "sla_list",
|
|
950
|
+
description: "List SLA definitions",
|
|
951
|
+
inputSchema: {
|
|
952
|
+
type: "object",
|
|
953
|
+
properties: {
|
|
954
|
+
query: { type: "string" },
|
|
955
|
+
limit: { type: "number", default: 20 },
|
|
956
|
+
},
|
|
957
|
+
},
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
name: "task_sla_list",
|
|
961
|
+
description: "List task SLAs (SLA records attached to tasks)",
|
|
962
|
+
inputSchema: {
|
|
963
|
+
type: "object",
|
|
964
|
+
properties: {
|
|
965
|
+
task_id: {
|
|
966
|
+
type: "string",
|
|
967
|
+
description: "Task sys_id to get SLAs for",
|
|
968
|
+
},
|
|
969
|
+
query: { type: "string" },
|
|
970
|
+
limit: { type: "number", default: 20 },
|
|
971
|
+
},
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: "task_sla_get",
|
|
976
|
+
description: "Get task SLA details",
|
|
977
|
+
inputSchema: {
|
|
978
|
+
type: "object",
|
|
979
|
+
properties: {
|
|
980
|
+
id: { type: "string", description: "Task SLA sys_id" },
|
|
981
|
+
},
|
|
982
|
+
required: ["id"],
|
|
983
|
+
},
|
|
984
|
+
},
|
|
985
|
+
// -------------------------------------------------------------------------
|
|
986
|
+
// WORKFLOW
|
|
987
|
+
// -------------------------------------------------------------------------
|
|
988
|
+
{
|
|
989
|
+
name: "workflow_list",
|
|
990
|
+
description: "List workflow definitions",
|
|
991
|
+
inputSchema: {
|
|
992
|
+
type: "object",
|
|
993
|
+
properties: {
|
|
994
|
+
query: { type: "string" },
|
|
995
|
+
active: { type: "boolean", default: true },
|
|
996
|
+
limit: { type: "number", default: 20 },
|
|
997
|
+
},
|
|
998
|
+
},
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
name: "workflow_context_list",
|
|
1002
|
+
description: "List workflow contexts (running workflow instances)",
|
|
1003
|
+
inputSchema: {
|
|
1004
|
+
type: "object",
|
|
1005
|
+
properties: {
|
|
1006
|
+
table: {
|
|
1007
|
+
type: "string",
|
|
1008
|
+
description: "Filter by table (e.g., incident)",
|
|
1009
|
+
},
|
|
1010
|
+
record_id: {
|
|
1011
|
+
type: "string",
|
|
1012
|
+
description: "Filter by record sys_id",
|
|
1013
|
+
},
|
|
1014
|
+
state: {
|
|
1015
|
+
type: "string",
|
|
1016
|
+
enum: ["executing", "finished", "cancelled"],
|
|
1017
|
+
},
|
|
1018
|
+
limit: { type: "number", default: 20 },
|
|
1019
|
+
},
|
|
1020
|
+
},
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
name: "workflow_context_get",
|
|
1024
|
+
description: "Get workflow context details",
|
|
1025
|
+
inputSchema: {
|
|
1026
|
+
type: "object",
|
|
1027
|
+
properties: {
|
|
1028
|
+
id: { type: "string", description: "Workflow context sys_id" },
|
|
1029
|
+
},
|
|
1030
|
+
required: ["id"],
|
|
1031
|
+
},
|
|
1032
|
+
},
|
|
1033
|
+
// -------------------------------------------------------------------------
|
|
1034
|
+
// EMAIL / NOTIFICATIONS
|
|
1035
|
+
// -------------------------------------------------------------------------
|
|
1036
|
+
{
|
|
1037
|
+
name: "email_list",
|
|
1038
|
+
description: "List emails (sys_email table)",
|
|
1039
|
+
inputSchema: {
|
|
1040
|
+
type: "object",
|
|
1041
|
+
properties: {
|
|
1042
|
+
query: { type: "string" },
|
|
1043
|
+
type: {
|
|
1044
|
+
type: "string",
|
|
1045
|
+
enum: ["sent", "received", "send-ready", "draft"],
|
|
1046
|
+
},
|
|
1047
|
+
limit: { type: "number", default: 20 },
|
|
1048
|
+
},
|
|
1049
|
+
},
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
name: "email_get",
|
|
1053
|
+
description: "Get email details",
|
|
1054
|
+
inputSchema: {
|
|
1055
|
+
type: "object",
|
|
1056
|
+
properties: {
|
|
1057
|
+
id: { type: "string", description: "Email sys_id" },
|
|
1058
|
+
},
|
|
1059
|
+
required: ["id"],
|
|
1060
|
+
},
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
name: "notification_list",
|
|
1064
|
+
description: "List email notification rules",
|
|
1065
|
+
inputSchema: {
|
|
1066
|
+
type: "object",
|
|
1067
|
+
properties: {
|
|
1068
|
+
table: { type: "string", description: "Filter by table" },
|
|
1069
|
+
active: { type: "boolean", default: true },
|
|
1070
|
+
limit: { type: "number", default: 20 },
|
|
1071
|
+
},
|
|
1072
|
+
},
|
|
1073
|
+
},
|
|
1074
|
+
// -------------------------------------------------------------------------
|
|
1075
|
+
// EVENTS
|
|
1076
|
+
// -------------------------------------------------------------------------
|
|
1077
|
+
{
|
|
1078
|
+
name: "event_list",
|
|
1079
|
+
description: "List system events (sysevent)",
|
|
1080
|
+
inputSchema: {
|
|
1081
|
+
type: "object",
|
|
1082
|
+
properties: {
|
|
1083
|
+
query: { type: "string" },
|
|
1084
|
+
name: { type: "string", description: "Event name filter" },
|
|
1085
|
+
limit: { type: "number", default: 20 },
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
},
|
|
1089
|
+
{
|
|
1090
|
+
name: "event_create",
|
|
1091
|
+
description: "Create/fire a system event",
|
|
1092
|
+
inputSchema: {
|
|
1093
|
+
type: "object",
|
|
1094
|
+
properties: {
|
|
1095
|
+
name: { type: "string", description: "Event name" },
|
|
1096
|
+
instance: {
|
|
1097
|
+
type: "string",
|
|
1098
|
+
description: "Record sys_id (parm1)",
|
|
1099
|
+
},
|
|
1100
|
+
parm2: { type: "string", description: "Parameter 2" },
|
|
1101
|
+
table: { type: "string", description: "Table name" },
|
|
1102
|
+
},
|
|
1103
|
+
required: ["name"],
|
|
1104
|
+
},
|
|
1105
|
+
},
|
|
1106
|
+
// -------------------------------------------------------------------------
|
|
1107
|
+
// JOURNAL / ACTIVITY STREAM
|
|
1108
|
+
// -------------------------------------------------------------------------
|
|
1109
|
+
{
|
|
1110
|
+
name: "journal_list",
|
|
1111
|
+
description: "List journal entries (work notes, comments) for a record",
|
|
1112
|
+
inputSchema: {
|
|
1113
|
+
type: "object",
|
|
1114
|
+
properties: {
|
|
1115
|
+
table: { type: "string", description: "Table name" },
|
|
1116
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1117
|
+
type: {
|
|
1118
|
+
type: "string",
|
|
1119
|
+
enum: ["work_notes", "comments", "all"],
|
|
1120
|
+
default: "all",
|
|
1121
|
+
},
|
|
1122
|
+
limit: { type: "number", default: 50 },
|
|
1123
|
+
},
|
|
1124
|
+
required: ["table", "id"],
|
|
1125
|
+
},
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
name: "activity_stream",
|
|
1129
|
+
description: "Get activity stream for a record (all changes, comments)",
|
|
1130
|
+
inputSchema: {
|
|
1131
|
+
type: "object",
|
|
1132
|
+
properties: {
|
|
1133
|
+
table: { type: "string", description: "Table name" },
|
|
1134
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1135
|
+
limit: { type: "number", default: 50 },
|
|
1136
|
+
},
|
|
1137
|
+
required: ["table", "id"],
|
|
1138
|
+
},
|
|
1139
|
+
},
|
|
1140
|
+
// -------------------------------------------------------------------------
|
|
1141
|
+
// AUDIT / HISTORY
|
|
1142
|
+
// -------------------------------------------------------------------------
|
|
1143
|
+
{
|
|
1144
|
+
name: "audit_list",
|
|
1145
|
+
description: "List audit history for a record",
|
|
1146
|
+
inputSchema: {
|
|
1147
|
+
type: "object",
|
|
1148
|
+
properties: {
|
|
1149
|
+
table: { type: "string", description: "Table name" },
|
|
1150
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1151
|
+
limit: { type: "number", default: 50 },
|
|
1152
|
+
},
|
|
1153
|
+
required: ["table", "id"],
|
|
1154
|
+
},
|
|
1155
|
+
},
|
|
1156
|
+
// -------------------------------------------------------------------------
|
|
1157
|
+
// SCHEDULED JOBS
|
|
1158
|
+
// -------------------------------------------------------------------------
|
|
1159
|
+
{
|
|
1160
|
+
name: "scheduled_job_list",
|
|
1161
|
+
description: "List scheduled jobs",
|
|
1162
|
+
inputSchema: {
|
|
1163
|
+
type: "object",
|
|
1164
|
+
properties: {
|
|
1165
|
+
query: { type: "string" },
|
|
1166
|
+
active: { type: "boolean", default: true },
|
|
1167
|
+
limit: { type: "number", default: 20 },
|
|
1168
|
+
},
|
|
1169
|
+
},
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
name: "scheduled_job_run",
|
|
1173
|
+
description: "Execute a scheduled job immediately",
|
|
1174
|
+
inputSchema: {
|
|
1175
|
+
type: "object",
|
|
1176
|
+
properties: {
|
|
1177
|
+
id: { type: "string", description: "Scheduled job sys_id" },
|
|
1178
|
+
},
|
|
1179
|
+
required: ["id"],
|
|
1180
|
+
},
|
|
1181
|
+
},
|
|
1182
|
+
// -------------------------------------------------------------------------
|
|
1183
|
+
// METRICS / PERFORMANCE ANALYTICS
|
|
1184
|
+
// -------------------------------------------------------------------------
|
|
1185
|
+
{
|
|
1186
|
+
name: "metric_list",
|
|
1187
|
+
description: "List defined metrics",
|
|
1188
|
+
inputSchema: {
|
|
1189
|
+
type: "object",
|
|
1190
|
+
properties: {
|
|
1191
|
+
query: { type: "string" },
|
|
1192
|
+
limit: { type: "number", default: 20 },
|
|
1193
|
+
},
|
|
1194
|
+
},
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
name: "metric_data",
|
|
1198
|
+
description: "Get metric data/values",
|
|
1199
|
+
inputSchema: {
|
|
1200
|
+
type: "object",
|
|
1201
|
+
properties: {
|
|
1202
|
+
metric_id: { type: "string", description: "Metric sys_id" },
|
|
1203
|
+
start_date: { type: "string", description: "Start date (ISO)" },
|
|
1204
|
+
end_date: { type: "string", description: "End date (ISO)" },
|
|
1205
|
+
},
|
|
1206
|
+
required: ["metric_id"],
|
|
1207
|
+
},
|
|
1208
|
+
},
|
|
1209
|
+
// -------------------------------------------------------------------------
|
|
1210
|
+
// UPDATE SETS
|
|
1211
|
+
// -------------------------------------------------------------------------
|
|
1212
|
+
{
|
|
1213
|
+
name: "update_set_list",
|
|
1214
|
+
description: "List update sets",
|
|
1215
|
+
inputSchema: {
|
|
1216
|
+
type: "object",
|
|
1217
|
+
properties: {
|
|
1218
|
+
query: { type: "string" },
|
|
1219
|
+
state: {
|
|
1220
|
+
type: "string",
|
|
1221
|
+
enum: ["in progress", "complete", "ignore"],
|
|
1222
|
+
},
|
|
1223
|
+
limit: { type: "number", default: 20 },
|
|
1224
|
+
},
|
|
1225
|
+
},
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
name: "update_set_get",
|
|
1229
|
+
description: "Get update set details with customer updates",
|
|
1230
|
+
inputSchema: {
|
|
1231
|
+
type: "object",
|
|
1232
|
+
properties: {
|
|
1233
|
+
id: { type: "string", description: "Update set sys_id" },
|
|
1234
|
+
},
|
|
1235
|
+
required: ["id"],
|
|
1236
|
+
},
|
|
1237
|
+
},
|
|
1238
|
+
// -------------------------------------------------------------------------
|
|
1239
|
+
// ASSET MANAGEMENT (ITAM)
|
|
1240
|
+
// -------------------------------------------------------------------------
|
|
1241
|
+
{
|
|
1242
|
+
name: "asset_list",
|
|
1243
|
+
description: "List assets (alm_asset)",
|
|
1244
|
+
inputSchema: {
|
|
1245
|
+
type: "object",
|
|
1246
|
+
properties: {
|
|
1247
|
+
query: { type: "string" },
|
|
1248
|
+
asset_tag: { type: "string", description: "Filter by asset tag" },
|
|
1249
|
+
state: {
|
|
1250
|
+
type: "string",
|
|
1251
|
+
enum: ["in_stock", "in_use", "on_order", "retired", "disposed"],
|
|
1252
|
+
},
|
|
1253
|
+
limit: { type: "number", default: 20 },
|
|
1254
|
+
},
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
name: "asset_get",
|
|
1259
|
+
description: "Get asset details",
|
|
1260
|
+
inputSchema: {
|
|
1261
|
+
type: "object",
|
|
1262
|
+
properties: {
|
|
1263
|
+
id: { type: "string", description: "Asset sys_id or asset_tag" },
|
|
1264
|
+
},
|
|
1265
|
+
required: ["id"],
|
|
1266
|
+
},
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
name: "asset_create",
|
|
1270
|
+
description: "Create an asset",
|
|
1271
|
+
inputSchema: {
|
|
1272
|
+
type: "object",
|
|
1273
|
+
properties: {
|
|
1274
|
+
asset_tag: { type: "string" },
|
|
1275
|
+
display_name: { type: "string" },
|
|
1276
|
+
model_category: { type: "string" },
|
|
1277
|
+
model: { type: "string", description: "Model sys_id" },
|
|
1278
|
+
serial_number: { type: "string" },
|
|
1279
|
+
assigned_to: { type: "string" },
|
|
1280
|
+
cost: { type: "number" },
|
|
1281
|
+
purchase_date: { type: "string" },
|
|
1282
|
+
},
|
|
1283
|
+
required: ["display_name"],
|
|
1284
|
+
},
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
name: "asset_update",
|
|
1288
|
+
description: "Update an asset",
|
|
1289
|
+
inputSchema: {
|
|
1290
|
+
type: "object",
|
|
1291
|
+
properties: {
|
|
1292
|
+
id: { type: "string", description: "Asset sys_id" },
|
|
1293
|
+
data: { type: "object", additionalProperties: true },
|
|
1294
|
+
},
|
|
1295
|
+
required: ["id", "data"],
|
|
1296
|
+
},
|
|
1297
|
+
},
|
|
1298
|
+
// -------------------------------------------------------------------------
|
|
1299
|
+
// SOFTWARE LICENSE MANAGEMENT
|
|
1300
|
+
// -------------------------------------------------------------------------
|
|
1301
|
+
{
|
|
1302
|
+
name: "license_list",
|
|
1303
|
+
description: "List software licenses (alm_license)",
|
|
1304
|
+
inputSchema: {
|
|
1305
|
+
type: "object",
|
|
1306
|
+
properties: {
|
|
1307
|
+
query: { type: "string" },
|
|
1308
|
+
product: { type: "string", description: "Software product name" },
|
|
1309
|
+
limit: { type: "number", default: 20 },
|
|
1310
|
+
},
|
|
1311
|
+
},
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
name: "license_get",
|
|
1315
|
+
description: "Get software license details",
|
|
1316
|
+
inputSchema: {
|
|
1317
|
+
type: "object",
|
|
1318
|
+
properties: {
|
|
1319
|
+
id: { type: "string", description: "License sys_id" },
|
|
1320
|
+
},
|
|
1321
|
+
required: ["id"],
|
|
1322
|
+
},
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
name: "license_entitlements",
|
|
1326
|
+
description: "List license entitlements/allocations",
|
|
1327
|
+
inputSchema: {
|
|
1328
|
+
type: "object",
|
|
1329
|
+
properties: {
|
|
1330
|
+
license_id: { type: "string", description: "License sys_id" },
|
|
1331
|
+
limit: { type: "number", default: 50 },
|
|
1332
|
+
},
|
|
1333
|
+
},
|
|
1334
|
+
},
|
|
1335
|
+
// -------------------------------------------------------------------------
|
|
1336
|
+
// SOFTWARE ASSET MANAGEMENT
|
|
1337
|
+
// -------------------------------------------------------------------------
|
|
1338
|
+
{
|
|
1339
|
+
name: "software_list",
|
|
1340
|
+
description: "List software installations",
|
|
1341
|
+
inputSchema: {
|
|
1342
|
+
type: "object",
|
|
1343
|
+
properties: {
|
|
1344
|
+
query: { type: "string" },
|
|
1345
|
+
publisher: { type: "string" },
|
|
1346
|
+
limit: { type: "number", default: 20 },
|
|
1347
|
+
},
|
|
1348
|
+
},
|
|
1349
|
+
},
|
|
1350
|
+
{
|
|
1351
|
+
name: "software_product_list",
|
|
1352
|
+
description: "List software products (software catalog)",
|
|
1353
|
+
inputSchema: {
|
|
1354
|
+
type: "object",
|
|
1355
|
+
properties: {
|
|
1356
|
+
query: { type: "string" },
|
|
1357
|
+
vendor: { type: "string" },
|
|
1358
|
+
limit: { type: "number", default: 20 },
|
|
1359
|
+
},
|
|
1360
|
+
},
|
|
1361
|
+
},
|
|
1362
|
+
// -------------------------------------------------------------------------
|
|
1363
|
+
// CONTRACTS
|
|
1364
|
+
// -------------------------------------------------------------------------
|
|
1365
|
+
{
|
|
1366
|
+
name: "contract_list",
|
|
1367
|
+
description: "List contracts",
|
|
1368
|
+
inputSchema: {
|
|
1369
|
+
type: "object",
|
|
1370
|
+
properties: {
|
|
1371
|
+
query: { type: "string" },
|
|
1372
|
+
type: { type: "string", description: "Contract type" },
|
|
1373
|
+
state: { type: "string" },
|
|
1374
|
+
limit: { type: "number", default: 20 },
|
|
1375
|
+
},
|
|
1376
|
+
},
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
name: "contract_get",
|
|
1380
|
+
description: "Get contract details",
|
|
1381
|
+
inputSchema: {
|
|
1382
|
+
type: "object",
|
|
1383
|
+
properties: {
|
|
1384
|
+
id: { type: "string", description: "Contract sys_id" },
|
|
1385
|
+
},
|
|
1386
|
+
required: ["id"],
|
|
1387
|
+
},
|
|
1388
|
+
},
|
|
1389
|
+
// -------------------------------------------------------------------------
|
|
1390
|
+
// LOCATION
|
|
1391
|
+
// -------------------------------------------------------------------------
|
|
1392
|
+
{
|
|
1393
|
+
name: "location_list",
|
|
1394
|
+
description: "List locations",
|
|
1395
|
+
inputSchema: {
|
|
1396
|
+
type: "object",
|
|
1397
|
+
properties: {
|
|
1398
|
+
query: { type: "string" },
|
|
1399
|
+
type: { type: "string", description: "Location type" },
|
|
1400
|
+
limit: { type: "number", default: 50 },
|
|
1401
|
+
},
|
|
1402
|
+
},
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
name: "location_get",
|
|
1406
|
+
description: "Get location details",
|
|
1407
|
+
inputSchema: {
|
|
1408
|
+
type: "object",
|
|
1409
|
+
properties: {
|
|
1410
|
+
id: { type: "string", description: "Location sys_id or name" },
|
|
1411
|
+
},
|
|
1412
|
+
required: ["id"],
|
|
1413
|
+
},
|
|
1414
|
+
},
|
|
1415
|
+
// -------------------------------------------------------------------------
|
|
1416
|
+
// DEPARTMENT / COST CENTER
|
|
1417
|
+
// -------------------------------------------------------------------------
|
|
1418
|
+
{
|
|
1419
|
+
name: "department_list",
|
|
1420
|
+
description: "List departments",
|
|
1421
|
+
inputSchema: {
|
|
1422
|
+
type: "object",
|
|
1423
|
+
properties: {
|
|
1424
|
+
query: { type: "string" },
|
|
1425
|
+
limit: { type: "number", default: 50 },
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
name: "cost_center_list",
|
|
1431
|
+
description: "List cost centers",
|
|
1432
|
+
inputSchema: {
|
|
1433
|
+
type: "object",
|
|
1434
|
+
properties: {
|
|
1435
|
+
query: { type: "string" },
|
|
1436
|
+
limit: { type: "number", default: 50 },
|
|
1437
|
+
},
|
|
1438
|
+
},
|
|
1439
|
+
},
|
|
1440
|
+
// -------------------------------------------------------------------------
|
|
1441
|
+
// DISCOVERY / ITOM
|
|
1442
|
+
// -------------------------------------------------------------------------
|
|
1443
|
+
{
|
|
1444
|
+
name: "discovery_status_list",
|
|
1445
|
+
description: "List discovery status records",
|
|
1446
|
+
inputSchema: {
|
|
1447
|
+
type: "object",
|
|
1448
|
+
properties: {
|
|
1449
|
+
query: { type: "string" },
|
|
1450
|
+
state: { type: "string", enum: ["active", "completed", "cancelled"] },
|
|
1451
|
+
limit: { type: "number", default: 20 },
|
|
1452
|
+
},
|
|
1453
|
+
},
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
name: "discovery_schedule_list",
|
|
1457
|
+
description: "List discovery schedules",
|
|
1458
|
+
inputSchema: {
|
|
1459
|
+
type: "object",
|
|
1460
|
+
properties: {
|
|
1461
|
+
query: { type: "string" },
|
|
1462
|
+
active: { type: "boolean", default: true },
|
|
1463
|
+
limit: { type: "number", default: 20 },
|
|
1464
|
+
},
|
|
1465
|
+
},
|
|
1466
|
+
},
|
|
1467
|
+
// -------------------------------------------------------------------------
|
|
1468
|
+
// SECURITY / ACL
|
|
1469
|
+
// -------------------------------------------------------------------------
|
|
1470
|
+
{
|
|
1471
|
+
name: "acl_list",
|
|
1472
|
+
description: "List access control rules",
|
|
1473
|
+
inputSchema: {
|
|
1474
|
+
type: "object",
|
|
1475
|
+
properties: {
|
|
1476
|
+
table: { type: "string", description: "Filter by table" },
|
|
1477
|
+
operation: {
|
|
1478
|
+
type: "string",
|
|
1479
|
+
enum: ["read", "write", "create", "delete"],
|
|
1480
|
+
},
|
|
1481
|
+
limit: { type: "number", default: 20 },
|
|
1482
|
+
},
|
|
1483
|
+
},
|
|
1484
|
+
},
|
|
1485
|
+
{
|
|
1486
|
+
name: "role_list",
|
|
1487
|
+
description: "List roles",
|
|
1488
|
+
inputSchema: {
|
|
1489
|
+
type: "object",
|
|
1490
|
+
properties: {
|
|
1491
|
+
query: { type: "string" },
|
|
1492
|
+
limit: { type: "number", default: 50 },
|
|
1493
|
+
},
|
|
1494
|
+
},
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
name: "user_roles",
|
|
1498
|
+
description: "Get roles for a user",
|
|
1499
|
+
inputSchema: {
|
|
1500
|
+
type: "object",
|
|
1501
|
+
properties: {
|
|
1502
|
+
user_id: { type: "string", description: "User sys_id" },
|
|
1503
|
+
},
|
|
1504
|
+
required: ["user_id"],
|
|
1505
|
+
},
|
|
1506
|
+
},
|
|
1507
|
+
// -------------------------------------------------------------------------
|
|
1508
|
+
// GENERIC / UTILITIES
|
|
1509
|
+
// -------------------------------------------------------------------------
|
|
1510
|
+
{
|
|
1511
|
+
name: "table_query",
|
|
1512
|
+
description: "Generic table query - query any ServiceNow table",
|
|
1513
|
+
inputSchema: {
|
|
1514
|
+
type: "object",
|
|
1515
|
+
properties: {
|
|
1516
|
+
table: {
|
|
1517
|
+
type: "string",
|
|
1518
|
+
description: "Table name (e.g., incident, sys_user, cmdb_ci)",
|
|
1519
|
+
},
|
|
1520
|
+
query: { type: "string", description: "Encoded query string" },
|
|
1521
|
+
fields: {
|
|
1522
|
+
type: "string",
|
|
1523
|
+
description: "Comma-separated fields to return",
|
|
1524
|
+
},
|
|
1525
|
+
limit: { type: "number", default: 20 },
|
|
1526
|
+
offset: { type: "number", default: 0 },
|
|
1527
|
+
order_by: { type: "string", description: "Field to order by" },
|
|
1528
|
+
order_dir: { type: "string", enum: ["asc", "desc"], default: "desc" },
|
|
1529
|
+
},
|
|
1530
|
+
required: ["table"],
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
{
|
|
1534
|
+
name: "table_get",
|
|
1535
|
+
description: "Get a single record from any table",
|
|
1536
|
+
inputSchema: {
|
|
1537
|
+
type: "object",
|
|
1538
|
+
properties: {
|
|
1539
|
+
table: { type: "string", description: "Table name" },
|
|
1540
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1541
|
+
fields: { type: "string", description: "Comma-separated fields" },
|
|
1542
|
+
},
|
|
1543
|
+
required: ["table", "id"],
|
|
1544
|
+
},
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
name: "table_create",
|
|
1548
|
+
description: "Create a record in any table",
|
|
1549
|
+
inputSchema: {
|
|
1550
|
+
type: "object",
|
|
1551
|
+
properties: {
|
|
1552
|
+
table: { type: "string", description: "Table name" },
|
|
1553
|
+
data: { type: "object", additionalProperties: true },
|
|
1554
|
+
},
|
|
1555
|
+
required: ["table", "data"],
|
|
1556
|
+
},
|
|
1557
|
+
},
|
|
1558
|
+
{
|
|
1559
|
+
name: "table_update",
|
|
1560
|
+
description: "Update a record in any table",
|
|
1561
|
+
inputSchema: {
|
|
1562
|
+
type: "object",
|
|
1563
|
+
properties: {
|
|
1564
|
+
table: { type: "string", description: "Table name" },
|
|
1565
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1566
|
+
data: { type: "object", additionalProperties: true },
|
|
1567
|
+
},
|
|
1568
|
+
required: ["table", "id", "data"],
|
|
1569
|
+
},
|
|
1570
|
+
},
|
|
1571
|
+
{
|
|
1572
|
+
name: "table_delete",
|
|
1573
|
+
description: "Delete a record from any table",
|
|
1574
|
+
inputSchema: {
|
|
1575
|
+
type: "object",
|
|
1576
|
+
properties: {
|
|
1577
|
+
table: { type: "string", description: "Table name" },
|
|
1578
|
+
id: { type: "string", description: "Record sys_id" },
|
|
1579
|
+
},
|
|
1580
|
+
required: ["table", "id"],
|
|
1581
|
+
},
|
|
1582
|
+
},
|
|
1583
|
+
{
|
|
1584
|
+
name: "aggregate",
|
|
1585
|
+
description: "Run aggregate queries (count, sum, avg, etc.)",
|
|
1586
|
+
inputSchema: {
|
|
1587
|
+
type: "object",
|
|
1588
|
+
properties: {
|
|
1589
|
+
table: { type: "string", description: "Table name" },
|
|
1590
|
+
query: { type: "string", description: "Filter query" },
|
|
1591
|
+
group_by: { type: "string", description: "Field to group by" },
|
|
1592
|
+
aggregate: {
|
|
1593
|
+
type: "string",
|
|
1594
|
+
enum: ["COUNT", "SUM", "AVG", "MIN", "MAX"],
|
|
1595
|
+
default: "COUNT",
|
|
1596
|
+
},
|
|
1597
|
+
having: { type: "string", description: "Having clause" },
|
|
1598
|
+
},
|
|
1599
|
+
required: ["table"],
|
|
1600
|
+
},
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
name: "table_schema",
|
|
1604
|
+
description: "Get table schema/dictionary information",
|
|
1605
|
+
inputSchema: {
|
|
1606
|
+
type: "object",
|
|
1607
|
+
properties: {
|
|
1608
|
+
table: { type: "string", description: "Table name" },
|
|
1609
|
+
},
|
|
1610
|
+
required: ["table"],
|
|
1611
|
+
},
|
|
1612
|
+
},
|
|
1613
|
+
{
|
|
1614
|
+
name: "choice_list",
|
|
1615
|
+
description: "Get choice list values for a field",
|
|
1616
|
+
inputSchema: {
|
|
1617
|
+
type: "object",
|
|
1618
|
+
properties: {
|
|
1619
|
+
table: { type: "string", description: "Table name" },
|
|
1620
|
+
field: { type: "string", description: "Field name" },
|
|
1621
|
+
},
|
|
1622
|
+
required: ["table", "field"],
|
|
1623
|
+
},
|
|
1624
|
+
},
|
|
1625
|
+
];
|
|
1626
|
+
// ============================================================================
|
|
1627
|
+
// ServiceNow API Client
|
|
1628
|
+
// ============================================================================
|
|
1629
|
+
class ServiceNowClient {
|
|
1630
|
+
baseUrl;
|
|
1631
|
+
authHeader;
|
|
1632
|
+
sessionCookies;
|
|
1633
|
+
userToken;
|
|
1634
|
+
authMethod;
|
|
1635
|
+
constructor() {
|
|
1636
|
+
// Priority: Browser auth > Basic auth > Session tokens
|
|
1637
|
+
if (browserAuth) {
|
|
1638
|
+
// Use browser-captured cookies
|
|
1639
|
+
this.baseUrl = browserAuth.instanceUrl;
|
|
1640
|
+
this.authHeader = "";
|
|
1641
|
+
this.sessionCookies = browserAuth.cookies;
|
|
1642
|
+
this.userToken = browserAuth.userToken;
|
|
1643
|
+
this.authMethod = "browser";
|
|
1644
|
+
console.error("Using browser-based SSO authentication");
|
|
1645
|
+
}
|
|
1646
|
+
else if (USERNAME && PASSWORD) {
|
|
1647
|
+
// Basic auth for REST Table API
|
|
1648
|
+
this.baseUrl = INSTANCE_URL.replace(/\/$/, "");
|
|
1649
|
+
this.authHeader =
|
|
1650
|
+
"Basic " + Buffer.from(`${USERNAME}:${PASSWORD}`).toString("base64");
|
|
1651
|
+
this.sessionCookies = "";
|
|
1652
|
+
this.userToken = "";
|
|
1653
|
+
this.authMethod = "basic";
|
|
1654
|
+
}
|
|
1655
|
+
else if (SESSION_TOKEN) {
|
|
1656
|
+
// Session-based auth for GraphQL
|
|
1657
|
+
this.baseUrl = INSTANCE_URL.replace(/\/$/, "");
|
|
1658
|
+
this.authHeader = "";
|
|
1659
|
+
this.sessionCookies = SESSION_TOKEN;
|
|
1660
|
+
this.userToken = USER_TOKEN;
|
|
1661
|
+
this.authMethod = "session";
|
|
1662
|
+
}
|
|
1663
|
+
else {
|
|
1664
|
+
// No auth configured - MCP will still start but tools will prompt for auth
|
|
1665
|
+
this.baseUrl = INSTANCE_URL.replace(/\/$/, "");
|
|
1666
|
+
this.authHeader = "";
|
|
1667
|
+
this.sessionCookies = "";
|
|
1668
|
+
this.userToken = "";
|
|
1669
|
+
this.authMethod = "none";
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
getAuthStatus() {
|
|
1673
|
+
return {
|
|
1674
|
+
method: this.authMethod,
|
|
1675
|
+
configured: this.authMethod !== "none",
|
|
1676
|
+
instanceUrl: this.baseUrl || "(not set)",
|
|
1677
|
+
details: this.authMethod === "browser"
|
|
1678
|
+
? "Using SSO cookies from browser authentication"
|
|
1679
|
+
: this.authMethod === "basic"
|
|
1680
|
+
? "Using username/password basic auth"
|
|
1681
|
+
: this.authMethod === "session"
|
|
1682
|
+
? "Using session token auth"
|
|
1683
|
+
: "No authentication configured. Use auth_browser tool or set credentials.",
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
// Reload browser auth cookies (called when 401 is received)
|
|
1687
|
+
reloadCredentials() {
|
|
1688
|
+
if (this.authMethod !== "browser") {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
if (reloadBrowserAuth() && browserAuth) {
|
|
1692
|
+
this.baseUrl = browserAuth.instanceUrl;
|
|
1693
|
+
this.sessionCookies = browserAuth.cookies;
|
|
1694
|
+
this.userToken = browserAuth.userToken;
|
|
1695
|
+
console.error("✅ ServiceNowClient credentials reloaded");
|
|
1696
|
+
return true;
|
|
1697
|
+
}
|
|
1698
|
+
return false;
|
|
1699
|
+
}
|
|
1700
|
+
// Validate session by making a lightweight API call
|
|
1701
|
+
async validateSession() {
|
|
1702
|
+
if (this.authMethod === "none") {
|
|
1703
|
+
return { valid: false, error: "No authentication configured" };
|
|
1704
|
+
}
|
|
1705
|
+
try {
|
|
1706
|
+
// Make a minimal API call to check session validity
|
|
1707
|
+
const url = `${this.baseUrl}/api/now/table/sys_user?sysparm_limit=1&sysparm_fields=sys_id`;
|
|
1708
|
+
const headers = {
|
|
1709
|
+
Accept: "application/json",
|
|
1710
|
+
};
|
|
1711
|
+
if (this.authMethod === "browser" && this.sessionCookies) {
|
|
1712
|
+
headers["Cookie"] = this.sessionCookies;
|
|
1713
|
+
}
|
|
1714
|
+
else if (this.authHeader) {
|
|
1715
|
+
headers["Authorization"] = this.authHeader;
|
|
1716
|
+
}
|
|
1717
|
+
const response = await fetch(url, { method: "GET", headers });
|
|
1718
|
+
if (response.status === 401) {
|
|
1719
|
+
return { valid: false, error: "Session expired (401 Unauthorized)" };
|
|
1720
|
+
}
|
|
1721
|
+
return { valid: response.ok };
|
|
1722
|
+
}
|
|
1723
|
+
catch (err) {
|
|
1724
|
+
return {
|
|
1725
|
+
valid: false,
|
|
1726
|
+
error: err instanceof Error ? err.message : "Validation failed",
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
checkConfig() {
|
|
1731
|
+
if (!this.baseUrl) {
|
|
1732
|
+
throw new Error("ServiceNow not configured. Set SERVICENOW_INSTANCE_URL environment variable.\n" +
|
|
1733
|
+
"Example: https://yourinstance.service-now.com");
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
async request(method, endpoint, body, useGraphQL = false) {
|
|
1737
|
+
this.checkConfig();
|
|
1738
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
1739
|
+
const headers = {
|
|
1740
|
+
"Content-Type": "application/json",
|
|
1741
|
+
Accept: "application/json",
|
|
1742
|
+
};
|
|
1743
|
+
// Apply authentication based on method
|
|
1744
|
+
if (this.authMethod === "browser" && this.sessionCookies) {
|
|
1745
|
+
// Browser auth - use cookies for all requests
|
|
1746
|
+
headers["Cookie"] = this.sessionCookies;
|
|
1747
|
+
if (this.userToken) {
|
|
1748
|
+
headers["x-usertoken"] = this.userToken;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
else if (useGraphQL && this.userToken) {
|
|
1752
|
+
headers["x-usertoken"] = this.userToken;
|
|
1753
|
+
if (this.sessionCookies) {
|
|
1754
|
+
headers["Cookie"] = this.sessionCookies;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
else if (this.authHeader) {
|
|
1758
|
+
headers["Authorization"] = this.authHeader;
|
|
1759
|
+
}
|
|
1760
|
+
else {
|
|
1761
|
+
throw new Error("No authentication configured. Options:\n" +
|
|
1762
|
+
"1. Use auth_browser tool to authenticate via SSO in browser\n" +
|
|
1763
|
+
"2. Set SERVICENOW_USERNAME + SERVICENOW_PASSWORD (for REST API)\n" +
|
|
1764
|
+
"3. Set SERVICENOW_SESSION_TOKEN + SERVICENOW_USER_TOKEN (for session auth)");
|
|
1765
|
+
}
|
|
1766
|
+
let response = await fetch(url, {
|
|
1767
|
+
method,
|
|
1768
|
+
headers,
|
|
1769
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
1770
|
+
});
|
|
1771
|
+
// Handle 401 with automatic cookie reload and retry (browser auth only)
|
|
1772
|
+
if (response.status === 401 && this.authMethod === "browser") {
|
|
1773
|
+
console.error("⚠️ Received 401 - attempting to reload cookies...");
|
|
1774
|
+
if (this.reloadCredentials()) {
|
|
1775
|
+
// Update headers with new cookies and retry
|
|
1776
|
+
headers["Cookie"] = this.sessionCookies;
|
|
1777
|
+
if (this.userToken) {
|
|
1778
|
+
headers["x-usertoken"] = this.userToken;
|
|
1779
|
+
}
|
|
1780
|
+
console.error("🔄 Retrying request with refreshed cookies...");
|
|
1781
|
+
response = await fetch(url, {
|
|
1782
|
+
method,
|
|
1783
|
+
headers,
|
|
1784
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
if (!response.ok) {
|
|
1789
|
+
const errorText = await response.text();
|
|
1790
|
+
throw new Error(`ServiceNow API error ${response.status}: ${errorText}`);
|
|
1791
|
+
}
|
|
1792
|
+
return response.json();
|
|
1793
|
+
}
|
|
1794
|
+
// REST Table API methods
|
|
1795
|
+
async tableQuery(table, params) {
|
|
1796
|
+
const searchParams = new URLSearchParams();
|
|
1797
|
+
if (params.query)
|
|
1798
|
+
searchParams.set("sysparm_query", params.query);
|
|
1799
|
+
if (params.fields)
|
|
1800
|
+
searchParams.set("sysparm_fields", params.fields);
|
|
1801
|
+
if (params.limit)
|
|
1802
|
+
searchParams.set("sysparm_limit", String(params.limit));
|
|
1803
|
+
if (params.offset)
|
|
1804
|
+
searchParams.set("sysparm_offset", String(params.offset));
|
|
1805
|
+
if (params.orderBy) {
|
|
1806
|
+
const dir = params.orderDir === "asc" ? "" : "DESC";
|
|
1807
|
+
searchParams.set("sysparm_query", `${params.query || ""}^ORDERBY${dir}${params.orderBy}`);
|
|
1808
|
+
}
|
|
1809
|
+
searchParams.set("sysparm_display_value", "true");
|
|
1810
|
+
return this.request("GET", `/api/now/table/${table}?${searchParams.toString()}`);
|
|
1811
|
+
}
|
|
1812
|
+
async tableGet(table, id, fields) {
|
|
1813
|
+
const searchParams = new URLSearchParams();
|
|
1814
|
+
if (fields)
|
|
1815
|
+
searchParams.set("sysparm_fields", fields);
|
|
1816
|
+
searchParams.set("sysparm_display_value", "true");
|
|
1817
|
+
return this.request("GET", `/api/now/table/${table}/${id}?${searchParams.toString()}`);
|
|
1818
|
+
}
|
|
1819
|
+
async tableCreate(table, data) {
|
|
1820
|
+
return this.request("POST", `/api/now/table/${table}`, data);
|
|
1821
|
+
}
|
|
1822
|
+
async tableUpdate(table, id, data) {
|
|
1823
|
+
return this.request("PATCH", `/api/now/table/${table}/${id}`, data);
|
|
1824
|
+
}
|
|
1825
|
+
async aggregate(table, params) {
|
|
1826
|
+
const searchParams = new URLSearchParams();
|
|
1827
|
+
if (params.query)
|
|
1828
|
+
searchParams.set("sysparm_query", params.query);
|
|
1829
|
+
if (params.groupBy)
|
|
1830
|
+
searchParams.set("sysparm_group_by", params.groupBy);
|
|
1831
|
+
searchParams.set("sysparm_count", "true");
|
|
1832
|
+
return this.request("GET", `/api/now/stats/${table}?${searchParams.toString()}`);
|
|
1833
|
+
}
|
|
1834
|
+
// GraphQL API for session-based queries
|
|
1835
|
+
async graphqlQuery(operationName, query, variables) {
|
|
1836
|
+
return this.request("POST", "/api/now/graphql", {
|
|
1837
|
+
operationName,
|
|
1838
|
+
query,
|
|
1839
|
+
variables,
|
|
1840
|
+
cacheable: false,
|
|
1841
|
+
}, true);
|
|
1842
|
+
}
|
|
1843
|
+
// Resolve number to sys_id for incidents, changes, etc.
|
|
1844
|
+
async resolveId(table, id) {
|
|
1845
|
+
if (id.length === 32 && /^[a-f0-9]+$/.test(id)) {
|
|
1846
|
+
return id; // Already a sys_id
|
|
1847
|
+
}
|
|
1848
|
+
// Look up by number
|
|
1849
|
+
const numberField = this.getNumberField(table);
|
|
1850
|
+
const result = (await this.tableQuery(table, {
|
|
1851
|
+
query: `${numberField}=${id}`,
|
|
1852
|
+
fields: "sys_id",
|
|
1853
|
+
limit: 1,
|
|
1854
|
+
}));
|
|
1855
|
+
if (result.result && result.result.length > 0) {
|
|
1856
|
+
return result.result[0].sys_id;
|
|
1857
|
+
}
|
|
1858
|
+
throw new Error(`Could not find ${table} with ${numberField}=${id}`);
|
|
1859
|
+
}
|
|
1860
|
+
getNumberField(table) {
|
|
1861
|
+
const numberFields = {
|
|
1862
|
+
incident: "number",
|
|
1863
|
+
change_request: "number",
|
|
1864
|
+
problem: "number",
|
|
1865
|
+
sc_request: "number",
|
|
1866
|
+
sc_req_item: "number",
|
|
1867
|
+
kb_knowledge: "number",
|
|
1868
|
+
task: "number",
|
|
1869
|
+
};
|
|
1870
|
+
return numberFields[table] || "number";
|
|
1871
|
+
}
|
|
1872
|
+
// Delete a record
|
|
1873
|
+
async tableDelete(table, id) {
|
|
1874
|
+
return this.request("DELETE", `/api/now/table/${table}/${id}`);
|
|
1875
|
+
}
|
|
1876
|
+
// Attachment API
|
|
1877
|
+
async attachmentGet(id) {
|
|
1878
|
+
return this.request("GET", `/api/now/attachment/${id}`);
|
|
1879
|
+
}
|
|
1880
|
+
async attachmentDownload(id) {
|
|
1881
|
+
// Returns file content
|
|
1882
|
+
return this.request("GET", `/api/now/attachment/${id}/file`);
|
|
1883
|
+
}
|
|
1884
|
+
async attachmentUpload(table, recordId, filename, content, contentType) {
|
|
1885
|
+
this.checkConfig();
|
|
1886
|
+
const url = `${this.baseUrl}/api/now/attachment/file?table_name=${table}&table_sys_id=${recordId}&file_name=${encodeURIComponent(filename)}`;
|
|
1887
|
+
const headers = {
|
|
1888
|
+
"Content-Type": contentType,
|
|
1889
|
+
Accept: "application/json",
|
|
1890
|
+
};
|
|
1891
|
+
if (this.authHeader) {
|
|
1892
|
+
headers["Authorization"] = this.authHeader;
|
|
1893
|
+
}
|
|
1894
|
+
// Decode base64 content
|
|
1895
|
+
const binaryContent = Buffer.from(content, "base64");
|
|
1896
|
+
const response = await fetch(url, {
|
|
1897
|
+
method: "POST",
|
|
1898
|
+
headers,
|
|
1899
|
+
body: binaryContent,
|
|
1900
|
+
});
|
|
1901
|
+
if (!response.ok) {
|
|
1902
|
+
const errorText = await response.text();
|
|
1903
|
+
throw new Error(`Attachment upload error ${response.status}: ${errorText}`);
|
|
1904
|
+
}
|
|
1905
|
+
return response.json();
|
|
1906
|
+
}
|
|
1907
|
+
async attachmentDelete(id) {
|
|
1908
|
+
return this.request("DELETE", `/api/now/attachment/${id}`);
|
|
1909
|
+
}
|
|
1910
|
+
// Service Catalog API (sn_sc)
|
|
1911
|
+
async catalogAddToCart(itemId, quantity, variables) {
|
|
1912
|
+
return this.request("POST", `/api/sn_sc/servicecatalog/items/${itemId}/add_to_cart`, { sysparm_quantity: quantity, variables });
|
|
1913
|
+
}
|
|
1914
|
+
async catalogGetCart() {
|
|
1915
|
+
return this.request("GET", "/api/sn_sc/servicecatalog/cart");
|
|
1916
|
+
}
|
|
1917
|
+
async catalogSubmitCart() {
|
|
1918
|
+
return this.request("POST", "/api/sn_sc/servicecatalog/cart/submit_order");
|
|
1919
|
+
}
|
|
1920
|
+
async catalogOrderNow(itemId, quantity, variables, requestedFor) {
|
|
1921
|
+
const body = {
|
|
1922
|
+
sysparm_quantity: quantity,
|
|
1923
|
+
variables,
|
|
1924
|
+
};
|
|
1925
|
+
if (requestedFor)
|
|
1926
|
+
body.sysparm_requested_for = requestedFor;
|
|
1927
|
+
return this.request("POST", `/api/sn_sc/servicecatalog/items/${itemId}/order_now`, body);
|
|
1928
|
+
}
|
|
1929
|
+
async catalogGetVariables(itemId) {
|
|
1930
|
+
return this.request("GET", `/api/sn_sc/servicecatalog/items/${itemId}/variables`);
|
|
1931
|
+
}
|
|
1932
|
+
// Import Set API
|
|
1933
|
+
async importSetLoad(table, data) {
|
|
1934
|
+
return this.request("POST", `/api/now/import/${table}`, data);
|
|
1935
|
+
}
|
|
1936
|
+
async importSetLoadMultiple(table, records) {
|
|
1937
|
+
return this.request("POST", `/api/now/import/${table}/insertMultiple`, {
|
|
1938
|
+
records,
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
// Batch API
|
|
1942
|
+
async batchRequest(requests) {
|
|
1943
|
+
return this.request("POST", "/api/now/v1/batch", {
|
|
1944
|
+
batch_request_id: `batch_${Date.now()}`,
|
|
1945
|
+
rest_requests: requests.map((r) => ({
|
|
1946
|
+
id: r.id,
|
|
1947
|
+
method: r.method,
|
|
1948
|
+
url: r.url,
|
|
1949
|
+
body: r.body ? JSON.stringify(r.body) : undefined,
|
|
1950
|
+
headers: r.headers
|
|
1951
|
+
? Object.entries(r.headers).map(([name, value]) => ({ name, value }))
|
|
1952
|
+
: [],
|
|
1953
|
+
})),
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
// CMDB Instance API
|
|
1957
|
+
async cmdbInstanceList(className, query, limit) {
|
|
1958
|
+
const params = new URLSearchParams();
|
|
1959
|
+
if (query)
|
|
1960
|
+
params.set("sysparm_query", query);
|
|
1961
|
+
if (limit)
|
|
1962
|
+
params.set("sysparm_limit", String(limit));
|
|
1963
|
+
return this.request("GET", `/api/now/cmdb/instance/${className}?${params.toString()}`);
|
|
1964
|
+
}
|
|
1965
|
+
// =========================================================================
|
|
1966
|
+
// UNIFIED WORK QUEUE METHODS (P1-P4 optimizations)
|
|
1967
|
+
// =========================================================================
|
|
1968
|
+
// Cache for user context (valid for session duration)
|
|
1969
|
+
userContextCache = null;
|
|
1970
|
+
async getMyContext() {
|
|
1971
|
+
// Return cached if available
|
|
1972
|
+
if (this.userContextCache) {
|
|
1973
|
+
return this.userContextCache;
|
|
1974
|
+
}
|
|
1975
|
+
// Get current user info
|
|
1976
|
+
const userResult = (await this.request("GET", "/api/now/table/sys_user?sysparm_query=user_name=javascript:gs.getUserName()&sysparm_limit=1&sysparm_fields=sys_id,user_name,name,email,title,department,manager"));
|
|
1977
|
+
const user = userResult.result?.[0] || {};
|
|
1978
|
+
const userId = user.sys_id;
|
|
1979
|
+
// Get user's group memberships (need both sys_id and display name)
|
|
1980
|
+
const groupsResult = (await this.request("GET", `/api/now/table/sys_user_grmember?sysparm_query=user=${userId}&sysparm_fields=group&sysparm_display_value=all`));
|
|
1981
|
+
const groups = (groupsResult.result || []).map((g) => ({
|
|
1982
|
+
sys_id: g.group?.value || "",
|
|
1983
|
+
name: g.group?.display_value || "",
|
|
1984
|
+
}));
|
|
1985
|
+
// Get user's roles
|
|
1986
|
+
const rolesResult = (await this.request("GET", `/api/now/table/sys_user_has_role?sysparm_query=user=${userId}&sysparm_fields=role&sysparm_display_value=true`));
|
|
1987
|
+
const roles = (rolesResult.result || []).map((r) => r.role?.display_value || "");
|
|
1988
|
+
// Cache and return
|
|
1989
|
+
this.userContextCache = { user, groups, roles };
|
|
1990
|
+
return this.userContextCache;
|
|
1991
|
+
}
|
|
1992
|
+
async getMyWorkQueue(params) {
|
|
1993
|
+
const include = params.include || ["assigned", "approvals", "group_queue"];
|
|
1994
|
+
const limit = params.limit || 20;
|
|
1995
|
+
const keyword = params.keyword;
|
|
1996
|
+
const results = {
|
|
1997
|
+
assigned: [],
|
|
1998
|
+
approvals: [],
|
|
1999
|
+
group_queue: [],
|
|
2000
|
+
};
|
|
2001
|
+
// Build keyword filter
|
|
2002
|
+
const keywordFilter = keyword ? `^short_descriptionLIKE${keyword}` : "";
|
|
2003
|
+
// 1. Get assigned tasks (if requested)
|
|
2004
|
+
if (include.includes("assigned")) {
|
|
2005
|
+
const assignedResult = (await this.tableQuery("task", {
|
|
2006
|
+
query: `assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true${keywordFilter}`,
|
|
2007
|
+
fields: "number,short_description,state,priority,sys_class_name,sys_updated_on,assignment_group",
|
|
2008
|
+
limit,
|
|
2009
|
+
}));
|
|
2010
|
+
results.assigned = assignedResult.result || [];
|
|
2011
|
+
}
|
|
2012
|
+
// 2. Get pending approvals with enriched parent data (if requested)
|
|
2013
|
+
if (include.includes("approvals")) {
|
|
2014
|
+
results.approvals = await this.getEnrichedApprovals({ keyword, limit });
|
|
2015
|
+
}
|
|
2016
|
+
// 3. Get unassigned group queue items (if requested)
|
|
2017
|
+
if (include.includes("group_queue")) {
|
|
2018
|
+
const context = await this.getMyContext();
|
|
2019
|
+
const groupIds = context.groups.map((g) => g.sys_id).join(",");
|
|
2020
|
+
if (groupIds) {
|
|
2021
|
+
const groupQueueResult = (await this.tableQuery("task", {
|
|
2022
|
+
query: `assignment_groupIN${groupIds}^assigned_toISEMPTY^active=true${keywordFilter}`,
|
|
2023
|
+
fields: "number,short_description,state,priority,sys_class_name,assignment_group,sys_created_on",
|
|
2024
|
+
limit,
|
|
2025
|
+
}));
|
|
2026
|
+
results.group_queue = groupQueueResult.result || [];
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
return {
|
|
2030
|
+
...results,
|
|
2031
|
+
summary: {
|
|
2032
|
+
total: results.assigned.length +
|
|
2033
|
+
results.approvals.length +
|
|
2034
|
+
results.group_queue.length,
|
|
2035
|
+
assigned: results.assigned.length,
|
|
2036
|
+
approvals: results.approvals.length,
|
|
2037
|
+
group_queue: results.group_queue.length,
|
|
2038
|
+
},
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
async getEnrichedApprovals(params) {
|
|
2042
|
+
const limit = params.limit || 20;
|
|
2043
|
+
// Get pending approvals
|
|
2044
|
+
const approvalsResult = (await this.tableQuery("sysapproval_approver", {
|
|
2045
|
+
query: "approverDYNAMIC90d1921e5f510100a9ad2572f2b477fe^state=requested",
|
|
2046
|
+
fields: "sys_id,sysapproval,state,sys_updated_on,document_id",
|
|
2047
|
+
limit: limit * 2, // Fetch more in case some get filtered out
|
|
2048
|
+
}));
|
|
2049
|
+
const approvals = approvalsResult.result || [];
|
|
2050
|
+
const enrichedApprovals = [];
|
|
2051
|
+
// Enrich each approval with parent record details
|
|
2052
|
+
for (const approval of approvals) {
|
|
2053
|
+
const docId = approval.document_id;
|
|
2054
|
+
const sysapproval = approval.sysapproval;
|
|
2055
|
+
if (!sysapproval?.link)
|
|
2056
|
+
continue;
|
|
2057
|
+
try {
|
|
2058
|
+
// Extract table and sys_id from the link
|
|
2059
|
+
const linkMatch = sysapproval.link.match(/\/table\/([^/]+)\/([^?]+)/);
|
|
2060
|
+
if (!linkMatch)
|
|
2061
|
+
continue;
|
|
2062
|
+
const [, table, parentSysId] = linkMatch;
|
|
2063
|
+
// Filter by type if specified
|
|
2064
|
+
if (params.type && params.type !== "all" && table !== params.type) {
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
// Fetch parent record details
|
|
2068
|
+
const parentResult = (await this.tableGet(table, parentSysId, "number,short_description,opened_by,opened_at,urgency,stage,state"));
|
|
2069
|
+
const parent = parentResult.result || {};
|
|
2070
|
+
// Filter by keyword if specified
|
|
2071
|
+
const shortDesc = parent.short_description || "";
|
|
2072
|
+
if (params.keyword &&
|
|
2073
|
+
!shortDesc.toLowerCase().includes(params.keyword.toLowerCase())) {
|
|
2074
|
+
continue;
|
|
2075
|
+
}
|
|
2076
|
+
enrichedApprovals.push({
|
|
2077
|
+
approval_sys_id: approval.sys_id,
|
|
2078
|
+
number: parent.number,
|
|
2079
|
+
short_description: parent.short_description,
|
|
2080
|
+
type: table,
|
|
2081
|
+
state: approval.state,
|
|
2082
|
+
opened_by: parent.opened_by?.display_value ||
|
|
2083
|
+
parent.opened_by,
|
|
2084
|
+
opened_at: parent.opened_at,
|
|
2085
|
+
urgency: parent.urgency,
|
|
2086
|
+
stage: parent.stage,
|
|
2087
|
+
waiting_since: approval.sys_updated_on,
|
|
2088
|
+
action: "approve",
|
|
2089
|
+
});
|
|
2090
|
+
if (enrichedApprovals.length >= limit)
|
|
2091
|
+
break;
|
|
2092
|
+
}
|
|
2093
|
+
catch {
|
|
2094
|
+
// Skip approvals we can't enrich
|
|
2095
|
+
continue;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
return enrichedApprovals;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
// ============================================================================
|
|
2102
|
+
// MCP Server
|
|
2103
|
+
// ============================================================================
|
|
2104
|
+
class ServiceNowMcpServer {
|
|
2105
|
+
server;
|
|
2106
|
+
client;
|
|
2107
|
+
constructor() {
|
|
2108
|
+
this.server = new Server({ name: "servicenow", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
2109
|
+
this.client = new ServiceNowClient();
|
|
2110
|
+
this.setupHandlers();
|
|
2111
|
+
}
|
|
2112
|
+
setupHandlers() {
|
|
2113
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
2114
|
+
tools: TOOLS,
|
|
2115
|
+
}));
|
|
2116
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2117
|
+
const { name, arguments: args } = request.params;
|
|
2118
|
+
try {
|
|
2119
|
+
const result = await this.handleTool(name, args);
|
|
2120
|
+
return {
|
|
2121
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
catch (error) {
|
|
2125
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2126
|
+
return {
|
|
2127
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
2128
|
+
isError: true,
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
async handleTool(name, args) {
|
|
2134
|
+
// Route to appropriate handler based on tool name
|
|
2135
|
+
const [category, action] = name.split("_");
|
|
2136
|
+
switch (name) {
|
|
2137
|
+
// Authentication
|
|
2138
|
+
case "auth_browser": {
|
|
2139
|
+
const instanceUrl = args.instance_url ||
|
|
2140
|
+
INSTANCE_URL ||
|
|
2141
|
+
"https://qvcprod.service-now.com";
|
|
2142
|
+
const result = await authenticateViaBrowser(instanceUrl);
|
|
2143
|
+
if (result.success) {
|
|
2144
|
+
// Hot-reload credentials without requiring restart
|
|
2145
|
+
const reloaded = this.client.reloadCredentials();
|
|
2146
|
+
return {
|
|
2147
|
+
status: "success",
|
|
2148
|
+
message: reloaded
|
|
2149
|
+
? "Browser authentication completed. Credentials reloaded - ready to use immediately."
|
|
2150
|
+
: "Browser authentication completed. Cookies saved. Note: If this is first auth, you may need to restart Claude.",
|
|
2151
|
+
instanceUrl: result.instanceUrl,
|
|
2152
|
+
cookieCount: result.cookies.length,
|
|
2153
|
+
hasUserToken: !!result.userToken,
|
|
2154
|
+
credentialsReloaded: reloaded,
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
else {
|
|
2158
|
+
throw new Error(result.error || "Browser authentication failed");
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
case "auth_status": {
|
|
2162
|
+
const status = this.client.getAuthStatus();
|
|
2163
|
+
const validation = await this.client.validateSession();
|
|
2164
|
+
return {
|
|
2165
|
+
...status,
|
|
2166
|
+
sessionValid: validation.valid,
|
|
2167
|
+
validationError: validation.error,
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
// Unified Work Queue
|
|
2171
|
+
case "my_context":
|
|
2172
|
+
return this.client.getMyContext();
|
|
2173
|
+
case "my_work_queue":
|
|
2174
|
+
return this.client.getMyWorkQueue({
|
|
2175
|
+
include: args.include,
|
|
2176
|
+
keyword: args.keyword,
|
|
2177
|
+
limit: args.limit,
|
|
2178
|
+
});
|
|
2179
|
+
// Incidents
|
|
2180
|
+
case "incidents_list":
|
|
2181
|
+
return this.client.tableQuery("incident", {
|
|
2182
|
+
query: args.query,
|
|
2183
|
+
fields: args.fields ||
|
|
2184
|
+
"number,short_description,state,priority,assigned_to,sys_updated_on",
|
|
2185
|
+
limit: args.limit || 20,
|
|
2186
|
+
offset: args.offset || 0,
|
|
2187
|
+
});
|
|
2188
|
+
case "incidents_get": {
|
|
2189
|
+
const id = await this.client.resolveId("incident", args.id);
|
|
2190
|
+
return this.client.tableGet("incident", id, args.fields);
|
|
2191
|
+
}
|
|
2192
|
+
case "incidents_create":
|
|
2193
|
+
return this.client.tableCreate("incident", args);
|
|
2194
|
+
case "incidents_update": {
|
|
2195
|
+
const id = await this.client.resolveId("incident", args.id);
|
|
2196
|
+
return this.client.tableUpdate("incident", id, args.data);
|
|
2197
|
+
}
|
|
2198
|
+
case "incidents_add_comment": {
|
|
2199
|
+
const id = await this.client.resolveId("incident", args.id);
|
|
2200
|
+
const field = args.type === "comments" ? "comments" : "work_notes";
|
|
2201
|
+
return this.client.tableUpdate("incident", id, {
|
|
2202
|
+
[field]: args.comment,
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
case "incidents_resolve": {
|
|
2206
|
+
const id = await this.client.resolveId("incident", args.id);
|
|
2207
|
+
return this.client.tableUpdate("incident", id, {
|
|
2208
|
+
state: 6, // Resolved
|
|
2209
|
+
close_code: args.resolution_code,
|
|
2210
|
+
close_notes: args.resolution_notes,
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
// Changes
|
|
2214
|
+
case "changes_list":
|
|
2215
|
+
return this.client.tableQuery("change_request", {
|
|
2216
|
+
query: args.query,
|
|
2217
|
+
fields: "number,short_description,state,type,start_date,end_date,assigned_to",
|
|
2218
|
+
limit: args.limit || 20,
|
|
2219
|
+
});
|
|
2220
|
+
case "changes_get": {
|
|
2221
|
+
const id = await this.client.resolveId("change_request", args.id);
|
|
2222
|
+
return this.client.tableGet("change_request", id);
|
|
2223
|
+
}
|
|
2224
|
+
case "changes_create":
|
|
2225
|
+
return this.client.tableCreate("change_request", args);
|
|
2226
|
+
case "changes_tasks": {
|
|
2227
|
+
const id = await this.client.resolveId("change_request", args.id);
|
|
2228
|
+
return this.client.tableQuery("change_task", {
|
|
2229
|
+
query: `change_request=${id}`,
|
|
2230
|
+
fields: "number,short_description,state,assigned_to,order",
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
// Service Catalog
|
|
2234
|
+
case "catalog_items":
|
|
2235
|
+
return this.client.tableQuery("sc_cat_item", {
|
|
2236
|
+
query: args.query
|
|
2237
|
+
? `nameLIKE${args.query}`
|
|
2238
|
+
: args.category
|
|
2239
|
+
? `category=${args.category}`
|
|
2240
|
+
: "active=true",
|
|
2241
|
+
fields: "name,short_description,category,price,sys_id",
|
|
2242
|
+
limit: args.limit || 20,
|
|
2243
|
+
});
|
|
2244
|
+
case "catalog_get":
|
|
2245
|
+
return this.client.tableGet("sc_cat_item", args.id);
|
|
2246
|
+
case "catalog_order":
|
|
2247
|
+
// Use the Service Catalog API for ordering
|
|
2248
|
+
return this.client.tableCreate("sc_request", {
|
|
2249
|
+
requested_for: args.requested_for,
|
|
2250
|
+
// Note: Full catalog ordering requires the SC API, not table API
|
|
2251
|
+
});
|
|
2252
|
+
case "requests_list":
|
|
2253
|
+
return this.client.tableQuery("sc_request", {
|
|
2254
|
+
query: args.my_requests
|
|
2255
|
+
? "requested_forDYNAMIC90d1921e5f510100a9ad2572f2b477fe"
|
|
2256
|
+
: args.query,
|
|
2257
|
+
fields: "number,short_description,request_state,opened_at,requested_for",
|
|
2258
|
+
limit: args.limit || 20,
|
|
2259
|
+
});
|
|
2260
|
+
case "requests_items":
|
|
2261
|
+
return this.client.tableQuery("sc_req_item", {
|
|
2262
|
+
query: args.query,
|
|
2263
|
+
fields: "number,short_description,stage,state,request,cat_item",
|
|
2264
|
+
limit: args.limit || 20,
|
|
2265
|
+
});
|
|
2266
|
+
// CMDB
|
|
2267
|
+
case "cmdb_search":
|
|
2268
|
+
return this.client.tableQuery(args.class || "cmdb_ci", {
|
|
2269
|
+
query: `nameLIKE${args.query}^ORasset_tagLIKE${args.query}`,
|
|
2270
|
+
fields: "name,sys_class_name,operational_status,install_status,location",
|
|
2271
|
+
limit: args.limit || 20,
|
|
2272
|
+
});
|
|
2273
|
+
case "cmdb_get":
|
|
2274
|
+
return this.client.tableGet(args.class || "cmdb_ci", args.id);
|
|
2275
|
+
case "cmdb_relationships":
|
|
2276
|
+
return this.client.tableQuery("cmdb_rel_ci", {
|
|
2277
|
+
query: `parent=${args.id}^ORchild=${args.id}`,
|
|
2278
|
+
fields: "parent,child,type",
|
|
2279
|
+
});
|
|
2280
|
+
// Problems
|
|
2281
|
+
case "problems_list":
|
|
2282
|
+
return this.client.tableQuery("problem", {
|
|
2283
|
+
query: args.query,
|
|
2284
|
+
fields: "number,short_description,state,priority,assigned_to",
|
|
2285
|
+
limit: args.limit || 20,
|
|
2286
|
+
});
|
|
2287
|
+
case "problems_get": {
|
|
2288
|
+
const id = await this.client.resolveId("problem", args.id);
|
|
2289
|
+
return this.client.tableGet("problem", id);
|
|
2290
|
+
}
|
|
2291
|
+
case "problems_create":
|
|
2292
|
+
return this.client.tableCreate("problem", args);
|
|
2293
|
+
// Knowledge
|
|
2294
|
+
case "knowledge_search":
|
|
2295
|
+
return this.client.tableQuery("kb_knowledge", {
|
|
2296
|
+
query: `textLIKE${args.query}^workflow_state=published`,
|
|
2297
|
+
fields: "number,short_description,text,sys_view_count",
|
|
2298
|
+
limit: args.limit || 10,
|
|
2299
|
+
});
|
|
2300
|
+
case "knowledge_get": {
|
|
2301
|
+
const id = await this.client.resolveId("kb_knowledge", args.id);
|
|
2302
|
+
return this.client.tableGet("kb_knowledge", id);
|
|
2303
|
+
}
|
|
2304
|
+
// Users & Groups
|
|
2305
|
+
case "users_search":
|
|
2306
|
+
return this.client.tableQuery("sys_user", {
|
|
2307
|
+
query: `nameLIKE${args.query}^ORuser_nameLIKE${args.query}^ORemailLIKE${args.query}`,
|
|
2308
|
+
fields: "user_name,name,email,department,title,manager,active",
|
|
2309
|
+
limit: args.limit || 10,
|
|
2310
|
+
});
|
|
2311
|
+
case "users_get":
|
|
2312
|
+
return this.client.tableGet("sys_user", args.id);
|
|
2313
|
+
case "groups_list":
|
|
2314
|
+
return this.client.tableQuery("sys_user_group", {
|
|
2315
|
+
query: args.query ? `nameLIKE${args.query}` : "",
|
|
2316
|
+
fields: "name,description,manager,type,active",
|
|
2317
|
+
limit: args.limit || 20,
|
|
2318
|
+
});
|
|
2319
|
+
case "groups_members": {
|
|
2320
|
+
// First resolve group if needed
|
|
2321
|
+
let groupId = args.id;
|
|
2322
|
+
if (!/^[a-f0-9]{32}$/.test(groupId)) {
|
|
2323
|
+
const groups = (await this.client.tableQuery("sys_user_group", {
|
|
2324
|
+
query: `name=${groupId}`,
|
|
2325
|
+
fields: "sys_id",
|
|
2326
|
+
limit: 1,
|
|
2327
|
+
}));
|
|
2328
|
+
if (groups.result?.length)
|
|
2329
|
+
groupId = groups.result[0].sys_id;
|
|
2330
|
+
}
|
|
2331
|
+
return this.client.tableQuery("sys_user_grmember", {
|
|
2332
|
+
query: `group=${groupId}`,
|
|
2333
|
+
fields: "user,group",
|
|
2334
|
+
});
|
|
2335
|
+
}
|
|
2336
|
+
// Tasks & Approvals
|
|
2337
|
+
case "tasks_my_tasks":
|
|
2338
|
+
return this.client.tableQuery("task", {
|
|
2339
|
+
query: "assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true",
|
|
2340
|
+
fields: "number,short_description,state,priority,sys_class_name",
|
|
2341
|
+
limit: args.limit || 20,
|
|
2342
|
+
});
|
|
2343
|
+
case "tasks_update": {
|
|
2344
|
+
const id = await this.client.resolveId("task", args.id);
|
|
2345
|
+
return this.client.tableUpdate("task", id, args.data);
|
|
2346
|
+
}
|
|
2347
|
+
case "approvals_pending":
|
|
2348
|
+
return this.client.getEnrichedApprovals({
|
|
2349
|
+
keyword: args.keyword,
|
|
2350
|
+
type: args.type,
|
|
2351
|
+
limit: args.limit || 20,
|
|
2352
|
+
});
|
|
2353
|
+
case "approvals_approve":
|
|
2354
|
+
return this.client.tableUpdate("sysapproval_approver", args.id, {
|
|
2355
|
+
state: "approved",
|
|
2356
|
+
comments: args.comments,
|
|
2357
|
+
});
|
|
2358
|
+
case "approvals_reject":
|
|
2359
|
+
return this.client.tableUpdate("sysapproval_approver", args.id, {
|
|
2360
|
+
state: "rejected",
|
|
2361
|
+
comments: args.comments,
|
|
2362
|
+
});
|
|
2363
|
+
// Generic table operations
|
|
2364
|
+
case "table_query":
|
|
2365
|
+
return this.client.tableQuery(args.table, {
|
|
2366
|
+
query: args.query,
|
|
2367
|
+
fields: args.fields,
|
|
2368
|
+
limit: args.limit || 20,
|
|
2369
|
+
offset: args.offset || 0,
|
|
2370
|
+
orderBy: args.order_by,
|
|
2371
|
+
orderDir: args.order_dir,
|
|
2372
|
+
});
|
|
2373
|
+
case "table_get":
|
|
2374
|
+
return this.client.tableGet(args.table, args.id, args.fields);
|
|
2375
|
+
case "table_create":
|
|
2376
|
+
return this.client.tableCreate(args.table, args.data);
|
|
2377
|
+
case "table_update":
|
|
2378
|
+
return this.client.tableUpdate(args.table, args.id, args.data);
|
|
2379
|
+
case "aggregate":
|
|
2380
|
+
return this.client.aggregate(args.table, {
|
|
2381
|
+
query: args.query,
|
|
2382
|
+
groupBy: args.group_by,
|
|
2383
|
+
aggregate: args.aggregate,
|
|
2384
|
+
});
|
|
2385
|
+
// Attachments (Full API)
|
|
2386
|
+
case "attachment_list":
|
|
2387
|
+
return this.client.tableQuery("sys_attachment", {
|
|
2388
|
+
query: `table_name=${args.table}^table_sys_id=${args.id}`,
|
|
2389
|
+
fields: "file_name,size_bytes,content_type,sys_created_on,sys_id",
|
|
2390
|
+
});
|
|
2391
|
+
case "attachment_get":
|
|
2392
|
+
return this.client.attachmentGet(args.id);
|
|
2393
|
+
case "attachment_download":
|
|
2394
|
+
return this.client.attachmentDownload(args.id);
|
|
2395
|
+
case "attachment_upload":
|
|
2396
|
+
return this.client.attachmentUpload(args.table, args.id, args.filename, args.content, args.content_type || "application/octet-stream");
|
|
2397
|
+
case "attachment_delete":
|
|
2398
|
+
return this.client.attachmentDelete(args.id);
|
|
2399
|
+
// Service Catalog (Full sn_sc API)
|
|
2400
|
+
case "catalog_categories":
|
|
2401
|
+
return this.client.tableQuery("sc_category", {
|
|
2402
|
+
query: args.catalog_id
|
|
2403
|
+
? `sc_catalog=${args.catalog_id}`
|
|
2404
|
+
: "active=true",
|
|
2405
|
+
fields: "title,description,sc_catalog,parent,sys_id",
|
|
2406
|
+
limit: args.limit || 50,
|
|
2407
|
+
});
|
|
2408
|
+
case "catalog_item_variables":
|
|
2409
|
+
return this.client.catalogGetVariables(args.id);
|
|
2410
|
+
case "catalog_add_to_cart":
|
|
2411
|
+
return this.client.catalogAddToCart(args.item_id, args.quantity || 1, args.variables || {});
|
|
2412
|
+
case "catalog_get_cart":
|
|
2413
|
+
return this.client.catalogGetCart();
|
|
2414
|
+
case "catalog_submit_cart":
|
|
2415
|
+
return this.client.catalogSubmitCart();
|
|
2416
|
+
case "catalog_order_now":
|
|
2417
|
+
return this.client.catalogOrderNow(args.item_id, args.quantity || 1, args.variables || {}, args.requested_for);
|
|
2418
|
+
// Import Set API
|
|
2419
|
+
case "import_set_load":
|
|
2420
|
+
return this.client.importSetLoad(args.table, args.data);
|
|
2421
|
+
case "import_set_load_multiple":
|
|
2422
|
+
return this.client.importSetLoadMultiple(args.table, args.records);
|
|
2423
|
+
case "import_set_status":
|
|
2424
|
+
return this.client.tableGet("sys_import_set", args.id);
|
|
2425
|
+
// Batch API
|
|
2426
|
+
case "batch_request":
|
|
2427
|
+
return this.client.batchRequest(args.requests);
|
|
2428
|
+
// CMDB Instance API (Advanced)
|
|
2429
|
+
case "cmdb_classes":
|
|
2430
|
+
return this.client.tableQuery("sys_db_object", {
|
|
2431
|
+
query: `super_class.name=${args.parent_class || "cmdb_ci"}`,
|
|
2432
|
+
fields: "name,label,super_class",
|
|
2433
|
+
limit: args.limit || 50,
|
|
2434
|
+
});
|
|
2435
|
+
case "cmdb_instance_list":
|
|
2436
|
+
return this.client.cmdbInstanceList(args.class_name, args.query, args.limit);
|
|
2437
|
+
case "cmdb_create":
|
|
2438
|
+
return this.client.tableCreate(args.class_name, args.data);
|
|
2439
|
+
case "cmdb_update":
|
|
2440
|
+
return this.client.tableUpdate(args.class_name || "cmdb_ci", args.id, args.data);
|
|
2441
|
+
case "cmdb_relationship_create":
|
|
2442
|
+
return this.client.tableCreate("cmdb_rel_ci", {
|
|
2443
|
+
parent: args.parent,
|
|
2444
|
+
child: args.child,
|
|
2445
|
+
type: args.type,
|
|
2446
|
+
});
|
|
2447
|
+
// Task SLA
|
|
2448
|
+
case "sla_list":
|
|
2449
|
+
return this.client.tableQuery("contract_sla", {
|
|
2450
|
+
query: args.query,
|
|
2451
|
+
fields: "name,type,table,duration,sys_id",
|
|
2452
|
+
limit: args.limit || 20,
|
|
2453
|
+
});
|
|
2454
|
+
case "task_sla_list":
|
|
2455
|
+
return this.client.tableQuery("task_sla", {
|
|
2456
|
+
query: args.task_id
|
|
2457
|
+
? `task=${args.task_id}`
|
|
2458
|
+
: args.query || "",
|
|
2459
|
+
fields: "task,sla,stage,has_breached,planned_end_time,end_time,percentage",
|
|
2460
|
+
limit: args.limit || 20,
|
|
2461
|
+
});
|
|
2462
|
+
case "task_sla_get":
|
|
2463
|
+
return this.client.tableGet("task_sla", args.id);
|
|
2464
|
+
// Workflow
|
|
2465
|
+
case "workflow_list":
|
|
2466
|
+
return this.client.tableQuery("wf_workflow", {
|
|
2467
|
+
query: args.active !== false ? "active=true" : args.query,
|
|
2468
|
+
fields: "name,table,description,active,sys_id",
|
|
2469
|
+
limit: args.limit || 20,
|
|
2470
|
+
});
|
|
2471
|
+
case "workflow_context_list": {
|
|
2472
|
+
let query = args.state ? `state=${args.state}` : "";
|
|
2473
|
+
if (args.table)
|
|
2474
|
+
query += `${query ? "^" : ""}table=${args.table}`;
|
|
2475
|
+
if (args.record_id)
|
|
2476
|
+
query += `${query ? "^" : ""}id=${args.record_id}`;
|
|
2477
|
+
return this.client.tableQuery("wf_context", {
|
|
2478
|
+
query,
|
|
2479
|
+
fields: "name,table,id,state,started,ended,workflow_version",
|
|
2480
|
+
limit: args.limit || 20,
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
case "workflow_context_get":
|
|
2484
|
+
return this.client.tableGet("wf_context", args.id);
|
|
2485
|
+
// Email / Notifications
|
|
2486
|
+
case "email_list": {
|
|
2487
|
+
let query = args.type ? `type=${args.type}` : "";
|
|
2488
|
+
if (args.query)
|
|
2489
|
+
query = args.query;
|
|
2490
|
+
return this.client.tableQuery("sys_email", {
|
|
2491
|
+
query,
|
|
2492
|
+
fields: "subject,recipients,type,state,sys_created_on,target_table,instance",
|
|
2493
|
+
limit: args.limit || 20,
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
case "email_get":
|
|
2497
|
+
return this.client.tableGet("sys_email", args.id);
|
|
2498
|
+
case "notification_list":
|
|
2499
|
+
return this.client.tableQuery("sysevent_email_action", {
|
|
2500
|
+
query: args.active !== false
|
|
2501
|
+
? `active=true${args.table ? `^collection=${args.table}` : ""}`
|
|
2502
|
+
: args.query,
|
|
2503
|
+
fields: "name,collection,event_name,recipient_fields,active",
|
|
2504
|
+
limit: args.limit || 20,
|
|
2505
|
+
});
|
|
2506
|
+
// Events
|
|
2507
|
+
case "event_list":
|
|
2508
|
+
return this.client.tableQuery("sysevent", {
|
|
2509
|
+
query: args.name ? `name=${args.name}` : args.query || "",
|
|
2510
|
+
fields: "name,parm1,parm2,table,sys_created_on,state",
|
|
2511
|
+
limit: args.limit || 20,
|
|
2512
|
+
});
|
|
2513
|
+
case "event_create":
|
|
2514
|
+
return this.client.tableCreate("sysevent", {
|
|
2515
|
+
name: args.name,
|
|
2516
|
+
parm1: args.instance,
|
|
2517
|
+
parm2: args.parm2,
|
|
2518
|
+
table: args.table,
|
|
2519
|
+
});
|
|
2520
|
+
// Journal / Activity Stream
|
|
2521
|
+
case "journal_list": {
|
|
2522
|
+
const journalTable = `sys_journal_field`;
|
|
2523
|
+
let query = `element_id=${args.id}^name=${args.table}`;
|
|
2524
|
+
if (args.type && args.type !== "all") {
|
|
2525
|
+
query += `^element=${args.type}`;
|
|
2526
|
+
}
|
|
2527
|
+
return this.client.tableQuery(journalTable, {
|
|
2528
|
+
query,
|
|
2529
|
+
fields: "element,value,sys_created_on,sys_created_by",
|
|
2530
|
+
limit: args.limit || 50,
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2533
|
+
case "activity_stream":
|
|
2534
|
+
return this.client.tableQuery("sys_history_line", {
|
|
2535
|
+
query: `set.id=${args.id}`,
|
|
2536
|
+
fields: "field,old,new,label,update_time,user",
|
|
2537
|
+
limit: args.limit || 50,
|
|
2538
|
+
});
|
|
2539
|
+
// Audit / History
|
|
2540
|
+
case "audit_list":
|
|
2541
|
+
return this.client.tableQuery("sys_audit", {
|
|
2542
|
+
query: `documentkey=${args.id}^tablename=${args.table}`,
|
|
2543
|
+
fields: "fieldname,oldvalue,newvalue,sys_created_on,user",
|
|
2544
|
+
limit: args.limit || 50,
|
|
2545
|
+
});
|
|
2546
|
+
// Scheduled Jobs
|
|
2547
|
+
case "scheduled_job_list":
|
|
2548
|
+
return this.client.tableQuery("sysauto", {
|
|
2549
|
+
query: args.active !== false ? "active=true" : args.query,
|
|
2550
|
+
fields: "name,run_type,run_dayofweek,run_time,active,sys_class_name",
|
|
2551
|
+
limit: args.limit || 20,
|
|
2552
|
+
});
|
|
2553
|
+
case "scheduled_job_run":
|
|
2554
|
+
// Trigger a scheduled job by updating its run field
|
|
2555
|
+
return this.client.tableUpdate("sysauto", args.id, {
|
|
2556
|
+
run_as_scheduled: true,
|
|
2557
|
+
});
|
|
2558
|
+
// Metrics / Performance Analytics
|
|
2559
|
+
case "metric_list":
|
|
2560
|
+
return this.client.tableQuery("pa_indicators", {
|
|
2561
|
+
query: args.query,
|
|
2562
|
+
fields: "name,description,unit,aggregate,frequency",
|
|
2563
|
+
limit: args.limit || 20,
|
|
2564
|
+
});
|
|
2565
|
+
case "metric_data": {
|
|
2566
|
+
let query = `indicator=${args.metric_id}`;
|
|
2567
|
+
if (args.start_date)
|
|
2568
|
+
query += `^sys_created_on>=${args.start_date}`;
|
|
2569
|
+
if (args.end_date)
|
|
2570
|
+
query += `^sys_created_on<=${args.end_date}`;
|
|
2571
|
+
return this.client.tableQuery("pa_scores", {
|
|
2572
|
+
query,
|
|
2573
|
+
fields: "indicator,value,date,breakdown,breakdown_value",
|
|
2574
|
+
limit: 100,
|
|
2575
|
+
});
|
|
2576
|
+
}
|
|
2577
|
+
// Update Sets
|
|
2578
|
+
case "update_set_list":
|
|
2579
|
+
return this.client.tableQuery("sys_update_set", {
|
|
2580
|
+
query: args.state
|
|
2581
|
+
? `state=${args.state}`
|
|
2582
|
+
: args.query || "",
|
|
2583
|
+
fields: "name,state,application,description,sys_created_on",
|
|
2584
|
+
limit: args.limit || 20,
|
|
2585
|
+
});
|
|
2586
|
+
case "update_set_get":
|
|
2587
|
+
return this.client.tableGet("sys_update_set", args.id);
|
|
2588
|
+
// Security / ACL
|
|
2589
|
+
case "acl_list": {
|
|
2590
|
+
let query = "";
|
|
2591
|
+
if (args.table)
|
|
2592
|
+
query += `name STARTSWITH ${args.table}`;
|
|
2593
|
+
if (args.operation)
|
|
2594
|
+
query += `${query ? "^" : ""}operation=${args.operation}`;
|
|
2595
|
+
return this.client.tableQuery("sys_security_acl", {
|
|
2596
|
+
query,
|
|
2597
|
+
fields: "name,operation,type,condition,script,active",
|
|
2598
|
+
limit: args.limit || 20,
|
|
2599
|
+
});
|
|
2600
|
+
}
|
|
2601
|
+
case "role_list":
|
|
2602
|
+
return this.client.tableQuery("sys_user_role", {
|
|
2603
|
+
query: args.query,
|
|
2604
|
+
fields: "name,description,grantable,assignable_by",
|
|
2605
|
+
limit: args.limit || 50,
|
|
2606
|
+
});
|
|
2607
|
+
case "user_roles":
|
|
2608
|
+
return this.client.tableQuery("sys_user_has_role", {
|
|
2609
|
+
query: `user=${args.user_id}`,
|
|
2610
|
+
fields: "role,granted_by,inherited",
|
|
2611
|
+
});
|
|
2612
|
+
// Asset Management (ITAM)
|
|
2613
|
+
case "asset_list": {
|
|
2614
|
+
let query = args.query || "";
|
|
2615
|
+
if (args.asset_tag)
|
|
2616
|
+
query = `asset_tag=${args.asset_tag}`;
|
|
2617
|
+
if (args.state)
|
|
2618
|
+
query += `${query ? "^" : ""}install_status=${args.state}`;
|
|
2619
|
+
return this.client.tableQuery("alm_asset", {
|
|
2620
|
+
query,
|
|
2621
|
+
fields: "asset_tag,display_name,model,serial_number,install_status,assigned_to,cost",
|
|
2622
|
+
limit: args.limit || 20,
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
case "asset_get": {
|
|
2626
|
+
const id = args.id;
|
|
2627
|
+
// Try by sys_id first, then by asset_tag
|
|
2628
|
+
if (/^[a-f0-9]{32}$/.test(id)) {
|
|
2629
|
+
return this.client.tableGet("alm_asset", id);
|
|
2630
|
+
}
|
|
2631
|
+
return this.client.tableQuery("alm_asset", {
|
|
2632
|
+
query: `asset_tag=${id}`,
|
|
2633
|
+
limit: 1,
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
case "asset_create":
|
|
2637
|
+
return this.client.tableCreate("alm_asset", args);
|
|
2638
|
+
case "asset_update":
|
|
2639
|
+
return this.client.tableUpdate("alm_asset", args.id, args.data);
|
|
2640
|
+
// Software License Management
|
|
2641
|
+
case "license_list":
|
|
2642
|
+
return this.client.tableQuery("alm_license", {
|
|
2643
|
+
query: args.product
|
|
2644
|
+
? `software_product.nameLIKE${args.product}`
|
|
2645
|
+
: args.query || "",
|
|
2646
|
+
fields: "software_product,start_date,end_date,quantity,license_type,cost",
|
|
2647
|
+
limit: args.limit || 20,
|
|
2648
|
+
});
|
|
2649
|
+
case "license_get":
|
|
2650
|
+
return this.client.tableGet("alm_license", args.id);
|
|
2651
|
+
case "license_entitlements":
|
|
2652
|
+
return this.client.tableQuery("alm_entitlement", {
|
|
2653
|
+
query: args.license_id ? `license=${args.license_id}` : "",
|
|
2654
|
+
fields: "license,user,allocated,start_date,end_date",
|
|
2655
|
+
limit: args.limit || 50,
|
|
2656
|
+
});
|
|
2657
|
+
// Software Asset Management
|
|
2658
|
+
case "software_list":
|
|
2659
|
+
return this.client.tableQuery("cmdb_sam_sw_install", {
|
|
2660
|
+
query: args.publisher
|
|
2661
|
+
? `publisherLIKE${args.publisher}`
|
|
2662
|
+
: args.query || "",
|
|
2663
|
+
fields: "display_name,publisher,version,installed_on,install_date",
|
|
2664
|
+
limit: args.limit || 20,
|
|
2665
|
+
});
|
|
2666
|
+
case "software_product_list":
|
|
2667
|
+
return this.client.tableQuery("cmdb_software_product_model", {
|
|
2668
|
+
query: args.vendor
|
|
2669
|
+
? `manufacturerLIKE${args.vendor}`
|
|
2670
|
+
: args.query || "",
|
|
2671
|
+
fields: "name,manufacturer,version,category",
|
|
2672
|
+
limit: args.limit || 20,
|
|
2673
|
+
});
|
|
2674
|
+
// Contracts
|
|
2675
|
+
case "contract_list":
|
|
2676
|
+
return this.client.tableQuery("ast_contract", {
|
|
2677
|
+
query: args.state
|
|
2678
|
+
? `state=${args.state}`
|
|
2679
|
+
: args.query || "",
|
|
2680
|
+
fields: "number,short_description,vendor,start_date,end_date,state,contract_value",
|
|
2681
|
+
limit: args.limit || 20,
|
|
2682
|
+
});
|
|
2683
|
+
case "contract_get":
|
|
2684
|
+
return this.client.tableGet("ast_contract", args.id);
|
|
2685
|
+
// Location
|
|
2686
|
+
case "location_list":
|
|
2687
|
+
return this.client.tableQuery("cmn_location", {
|
|
2688
|
+
query: args.query || "",
|
|
2689
|
+
fields: "name,street,city,state,country,zip,latitude,longitude,parent",
|
|
2690
|
+
limit: args.limit || 50,
|
|
2691
|
+
});
|
|
2692
|
+
case "location_get": {
|
|
2693
|
+
const id = args.id;
|
|
2694
|
+
if (/^[a-f0-9]{32}$/.test(id)) {
|
|
2695
|
+
return this.client.tableGet("cmn_location", id);
|
|
2696
|
+
}
|
|
2697
|
+
return this.client.tableQuery("cmn_location", {
|
|
2698
|
+
query: `name=${id}`,
|
|
2699
|
+
limit: 1,
|
|
2700
|
+
});
|
|
2701
|
+
}
|
|
2702
|
+
// Department / Cost Center
|
|
2703
|
+
case "department_list":
|
|
2704
|
+
return this.client.tableQuery("cmn_department", {
|
|
2705
|
+
query: args.query || "",
|
|
2706
|
+
fields: "name,head,cost_center,description,parent",
|
|
2707
|
+
limit: args.limit || 50,
|
|
2708
|
+
});
|
|
2709
|
+
case "cost_center_list":
|
|
2710
|
+
return this.client.tableQuery("cmn_cost_center", {
|
|
2711
|
+
query: args.query || "",
|
|
2712
|
+
fields: "name,account_number,manager,valid_from,valid_to",
|
|
2713
|
+
limit: args.limit || 50,
|
|
2714
|
+
});
|
|
2715
|
+
// Discovery / ITOM
|
|
2716
|
+
case "discovery_status_list":
|
|
2717
|
+
return this.client.tableQuery("discovery_status", {
|
|
2718
|
+
query: args.state
|
|
2719
|
+
? `state=${args.state}`
|
|
2720
|
+
: args.query || "",
|
|
2721
|
+
fields: "name,state,type,schedule,started,completed,scanned_devices",
|
|
2722
|
+
limit: args.limit || 20,
|
|
2723
|
+
});
|
|
2724
|
+
case "discovery_schedule_list":
|
|
2725
|
+
return this.client.tableQuery("discovery_schedule", {
|
|
2726
|
+
query: args.active !== false
|
|
2727
|
+
? "active=true"
|
|
2728
|
+
: args.query || "",
|
|
2729
|
+
fields: "name,discover,run_type,run_time,max_run_time,active",
|
|
2730
|
+
limit: args.limit || 20,
|
|
2731
|
+
});
|
|
2732
|
+
// Table delete
|
|
2733
|
+
case "table_delete":
|
|
2734
|
+
return this.client.tableDelete(args.table, args.id);
|
|
2735
|
+
// Table schema
|
|
2736
|
+
case "table_schema":
|
|
2737
|
+
return this.client.tableQuery("sys_dictionary", {
|
|
2738
|
+
query: `name=${args.table}`,
|
|
2739
|
+
fields: "element,column_label,internal_type,max_length,mandatory,reference",
|
|
2740
|
+
limit: 200,
|
|
2741
|
+
});
|
|
2742
|
+
// Choice list
|
|
2743
|
+
case "choice_list":
|
|
2744
|
+
return this.client.tableQuery("sys_choice", {
|
|
2745
|
+
query: `name=${args.table}^element=${args.field}`,
|
|
2746
|
+
fields: "value,label,sequence,inactive",
|
|
2747
|
+
});
|
|
2748
|
+
default:
|
|
2749
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
async run() {
|
|
2753
|
+
const transport = new StdioServerTransport();
|
|
2754
|
+
await this.server.connect(transport);
|
|
2755
|
+
console.error("ServiceNow MCP server running on stdio");
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
const server = new ServiceNowMcpServer();
|
|
2759
|
+
server.run().catch(console.error);
|