snow-flow 3.3.0 → 3.3.2

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.
@@ -0,0 +1,860 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * ServiceNow Flow Designer, Agent Workspace & Mobile MCP Server - ENHANCED VERSION
5
+ * With logging, token tracking, and progress indicators
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
9
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
10
+ const enhanced_base_mcp_server_js_1 = require("./shared/enhanced-base-mcp-server.js");
11
+ const mcp_config_manager_js_1 = require("../utils/mcp-config-manager.js");
12
+ class ServiceNowFlowWorkspaceMobileMCPEnhanced extends enhanced_base_mcp_server_js_1.EnhancedBaseMCPServer {
13
+ constructor() {
14
+ super('servicenow-flow-workspace-mobile-enhanced', '2.0.0');
15
+ this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
16
+ this.setupHandlers();
17
+ }
18
+ setupHandlers() {
19
+ this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
20
+ tools: [
21
+ // Flow Designer Tools
22
+ {
23
+ name: 'snow_create_flow',
24
+ description: 'Creates flow in Flow Designer using sys_hub_flow table.',
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ name: { type: 'string', description: 'Flow name' },
29
+ description: { type: 'string', description: 'Flow description' },
30
+ application: { type: 'string', description: 'Application scope' },
31
+ active: { type: 'boolean', default: false },
32
+ run_as: { type: 'string', description: 'Run as user: user_who_initiates, system' }
33
+ },
34
+ required: ['name']
35
+ }
36
+ },
37
+ {
38
+ name: 'snow_create_flow_action',
39
+ description: 'Creates flow action using sys_hub_action_instance table.',
40
+ inputSchema: {
41
+ type: 'object',
42
+ properties: {
43
+ flow: { type: 'string', description: 'Flow sys_id' },
44
+ action_type: { type: 'string', description: 'Action type' },
45
+ action_name: { type: 'string', description: 'Action name' },
46
+ inputs: { type: 'object', description: 'Action inputs' },
47
+ order: { type: 'number', description: 'Execution order' }
48
+ },
49
+ required: ['flow', 'action_type']
50
+ }
51
+ },
52
+ {
53
+ name: 'snow_create_subflow',
54
+ description: 'Creates reusable subflow using sys_hub_sub_flow table.',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {
58
+ name: { type: 'string', description: 'Subflow name' },
59
+ description: { type: 'string', description: 'Subflow description' },
60
+ inputs: { type: 'array', items: { type: 'object' }, description: 'Input variables' },
61
+ outputs: { type: 'array', items: { type: 'object' }, description: 'Output variables' }
62
+ },
63
+ required: ['name']
64
+ }
65
+ },
66
+ {
67
+ name: 'snow_add_flow_trigger',
68
+ description: 'Adds trigger to flow using sys_hub_trigger_instance table.',
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ flow: { type: 'string', description: 'Flow sys_id' },
73
+ trigger_type: { type: 'string', description: 'record, schedule, inbound_email' },
74
+ table: { type: 'string', description: 'Table name for record trigger' },
75
+ condition: { type: 'string', description: 'Trigger condition' },
76
+ schedule: { type: 'string', description: 'Schedule for time-based trigger' }
77
+ },
78
+ required: ['flow', 'trigger_type']
79
+ }
80
+ },
81
+ {
82
+ name: 'snow_publish_flow',
83
+ description: 'Publishes and activates flow in sys_hub_flow table.',
84
+ inputSchema: {
85
+ type: 'object',
86
+ properties: {
87
+ flow_id: { type: 'string', description: 'Flow sys_id' },
88
+ version: { type: 'string', description: 'Version number' },
89
+ activate: { type: 'boolean', default: true }
90
+ },
91
+ required: ['flow_id']
92
+ }
93
+ },
94
+ {
95
+ name: 'snow_test_flow',
96
+ description: 'Tests flow execution using sys_flow_context table.',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ flow_id: { type: 'string', description: 'Flow sys_id' },
101
+ test_data: { type: 'object', description: 'Test input data' },
102
+ debug: { type: 'boolean', default: true }
103
+ },
104
+ required: ['flow_id']
105
+ }
106
+ },
107
+ {
108
+ name: 'snow_get_flow_execution_details',
109
+ description: 'Gets flow execution history from sys_flow_context table.',
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ flow_id: { type: 'string', description: 'Flow sys_id' },
114
+ execution_id: { type: 'string', description: 'Specific execution ID' },
115
+ status: { type: 'string', description: 'Filter by status' },
116
+ limit: { type: 'number', default: 10 }
117
+ }
118
+ }
119
+ },
120
+ // Agent Workspace Tools
121
+ {
122
+ name: 'snow_create_workspace',
123
+ description: 'Creates agent workspace using sys_aw_workspace table.',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ name: { type: 'string', description: 'Workspace name' },
128
+ description: { type: 'string', description: 'Workspace description' },
129
+ roles: { type: 'array', items: { type: 'string' }, description: 'Required roles' },
130
+ default_landing_page: { type: 'string', description: 'Landing page' },
131
+ branding: { type: 'object', description: 'Branding configuration' }
132
+ },
133
+ required: ['name']
134
+ }
135
+ },
136
+ {
137
+ name: 'snow_configure_workspace_tab',
138
+ description: 'Configures workspace tabs using sys_aw_tab table.',
139
+ inputSchema: {
140
+ type: 'object',
141
+ properties: {
142
+ workspace: { type: 'string', description: 'Workspace sys_id' },
143
+ label: { type: 'string', description: 'Tab label' },
144
+ url: { type: 'string', description: 'Tab URL or page' },
145
+ order: { type: 'number', description: 'Tab order' },
146
+ icon: { type: 'string', description: 'Tab icon' }
147
+ },
148
+ required: ['workspace', 'label']
149
+ }
150
+ },
151
+ {
152
+ name: 'snow_add_workspace_list',
153
+ description: 'Adds lists to workspace using sys_aw_list table.',
154
+ inputSchema: {
155
+ type: 'object',
156
+ properties: {
157
+ workspace: { type: 'string', description: 'Workspace sys_id' },
158
+ table: { type: 'string', description: 'Table name' },
159
+ filter: { type: 'string', description: 'List filter' },
160
+ columns: { type: 'array', items: { type: 'string' }, description: 'Display columns' },
161
+ order_by: { type: 'string', description: 'Sort order' }
162
+ },
163
+ required: ['workspace', 'table']
164
+ }
165
+ },
166
+ {
167
+ name: 'snow_create_workspace_form',
168
+ description: 'Creates workspace forms using sys_aw_form table.',
169
+ inputSchema: {
170
+ type: 'object',
171
+ properties: {
172
+ workspace: { type: 'string', description: 'Workspace sys_id' },
173
+ table: { type: 'string', description: 'Table name' },
174
+ sections: { type: 'array', items: { type: 'object' }, description: 'Form sections' },
175
+ fields: { type: 'array', items: { type: 'string' }, description: 'Form fields' }
176
+ },
177
+ required: ['workspace', 'table']
178
+ }
179
+ },
180
+ {
181
+ name: 'snow_configure_workspace_ui_action',
182
+ description: 'Adds UI actions to workspace using sys_aw_ui_action table.',
183
+ inputSchema: {
184
+ type: 'object',
185
+ properties: {
186
+ workspace: { type: 'string', description: 'Workspace sys_id' },
187
+ name: { type: 'string', description: 'Action name' },
188
+ label: { type: 'string', description: 'Action label' },
189
+ script: { type: 'string', description: 'Action script' },
190
+ condition: { type: 'string', description: 'Display condition' }
191
+ },
192
+ required: ['workspace', 'name', 'label']
193
+ }
194
+ },
195
+ {
196
+ name: 'snow_deploy_workspace',
197
+ description: 'Deploys workspace to agents using sys_aw_workspace table.',
198
+ inputSchema: {
199
+ type: 'object',
200
+ properties: {
201
+ workspace_id: { type: 'string', description: 'Workspace sys_id' },
202
+ activate: { type: 'boolean', default: true },
203
+ roles: { type: 'array', items: { type: 'string' }, description: 'Target roles' }
204
+ },
205
+ required: ['workspace_id']
206
+ }
207
+ },
208
+ // Mobile Platform Tools
209
+ {
210
+ name: 'snow_create_mobile_app_config',
211
+ description: 'Creates mobile app configuration using sys_mobile_config table.',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {
215
+ name: { type: 'string', description: 'App name' },
216
+ description: { type: 'string', description: 'App description' },
217
+ app_id: { type: 'string', description: 'Application ID' },
218
+ version: { type: 'string', description: 'App version' },
219
+ platforms: { type: 'array', items: { type: 'string' }, description: 'ios, android' }
220
+ },
221
+ required: ['name', 'app_id']
222
+ }
223
+ },
224
+ {
225
+ name: 'snow_configure_mobile_layout',
226
+ description: 'Configures mobile layouts using sys_mobile_layout table.',
227
+ inputSchema: {
228
+ type: 'object',
229
+ properties: {
230
+ app_config: { type: 'string', description: 'App config sys_id' },
231
+ name: { type: 'string', description: 'Layout name' },
232
+ type: { type: 'string', description: 'list, form, dashboard' },
233
+ components: { type: 'array', items: { type: 'object' }, description: 'Layout components' }
234
+ },
235
+ required: ['app_config', 'name', 'type']
236
+ }
237
+ },
238
+ {
239
+ name: 'snow_create_mobile_applet',
240
+ description: 'Creates mobile applet using sys_mobile_applet table.',
241
+ inputSchema: {
242
+ type: 'object',
243
+ properties: {
244
+ name: { type: 'string', description: 'Applet name' },
245
+ table: { type: 'string', description: 'Data table' },
246
+ layout: { type: 'string', description: 'Layout sys_id' },
247
+ icon: { type: 'string', description: 'Applet icon' },
248
+ order: { type: 'number', description: 'Display order' }
249
+ },
250
+ required: ['name', 'table']
251
+ }
252
+ },
253
+ {
254
+ name: 'snow_configure_offline_tables',
255
+ description: 'Configures offline data sync using sys_mobile_offline table.',
256
+ inputSchema: {
257
+ type: 'object',
258
+ properties: {
259
+ app_config: { type: 'string', description: 'App config sys_id' },
260
+ tables: { type: 'array', items: { type: 'string' }, description: 'Tables to sync' },
261
+ sync_rules: { type: 'object', description: 'Sync conditions' },
262
+ frequency: { type: 'string', description: 'Sync frequency' }
263
+ },
264
+ required: ['app_config', 'tables']
265
+ }
266
+ },
267
+ {
268
+ name: 'snow_set_mobile_security',
269
+ description: 'Sets mobile security policies using sys_mobile_security table.',
270
+ inputSchema: {
271
+ type: 'object',
272
+ properties: {
273
+ app_config: { type: 'string', description: 'App config sys_id' },
274
+ require_pin: { type: 'boolean', default: true },
275
+ biometric_auth: { type: 'boolean', default: false },
276
+ session_timeout: { type: 'number', description: 'Timeout in minutes' },
277
+ data_encryption: { type: 'boolean', default: true }
278
+ },
279
+ required: ['app_config']
280
+ }
281
+ },
282
+ {
283
+ name: 'snow_push_notification_config',
284
+ description: 'Configures push notifications using sys_push_notification table.',
285
+ inputSchema: {
286
+ type: 'object',
287
+ properties: {
288
+ app_config: { type: 'string', description: 'App config sys_id' },
289
+ event_types: { type: 'array', items: { type: 'string' }, description: 'Event types' },
290
+ templates: { type: 'object', description: 'Message templates' },
291
+ enabled: { type: 'boolean', default: true }
292
+ },
293
+ required: ['app_config', 'event_types']
294
+ }
295
+ },
296
+ {
297
+ name: 'snow_deploy_mobile_app',
298
+ description: 'Deploys mobile app using sys_mobile_deployment table.',
299
+ inputSchema: {
300
+ type: 'object',
301
+ properties: {
302
+ app_config_id: { type: 'string', description: 'App config sys_id' },
303
+ environment: { type: 'string', description: 'dev, test, prod' },
304
+ deploy_to_stores: { type: 'boolean', default: false },
305
+ release_notes: { type: 'string', description: 'Release notes' }
306
+ },
307
+ required: ['app_config_id', 'environment']
308
+ }
309
+ }
310
+ ]
311
+ }));
312
+ this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
313
+ try {
314
+ const { name, arguments: args } = request.params;
315
+ // Execute with enhanced tracking
316
+ return await this.executeTool(name, async () => {
317
+ switch (name) {
318
+ // Flow Designer
319
+ case 'snow_create_flow':
320
+ return await this.createFlow(args);
321
+ case 'snow_create_flow_action':
322
+ return await this.createFlowAction(args);
323
+ case 'snow_create_subflow':
324
+ return await this.createSubflow(args);
325
+ case 'snow_add_flow_trigger':
326
+ return await this.addFlowTrigger(args);
327
+ case 'snow_publish_flow':
328
+ return await this.publishFlow(args);
329
+ case 'snow_test_flow':
330
+ return await this.testFlow(args);
331
+ case 'snow_get_flow_execution_details':
332
+ return await this.getFlowExecutionDetails(args);
333
+ // Agent Workspace
334
+ case 'snow_create_workspace':
335
+ return await this.createWorkspace(args);
336
+ case 'snow_configure_workspace_tab':
337
+ return await this.configureWorkspaceTab(args);
338
+ case 'snow_add_workspace_list':
339
+ return await this.addWorkspaceList(args);
340
+ case 'snow_create_workspace_form':
341
+ return await this.createWorkspaceForm(args);
342
+ case 'snow_configure_workspace_ui_action':
343
+ return await this.configureWorkspaceUIAction(args);
344
+ case 'snow_deploy_workspace':
345
+ return await this.deployWorkspace(args);
346
+ // Mobile Platform
347
+ case 'snow_create_mobile_app_config':
348
+ return await this.createMobileAppConfig(args);
349
+ case 'snow_configure_mobile_layout':
350
+ return await this.configureMobileLayout(args);
351
+ case 'snow_create_mobile_applet':
352
+ return await this.createMobileApplet(args);
353
+ case 'snow_configure_offline_tables':
354
+ return await this.configureOfflineTables(args);
355
+ case 'snow_set_mobile_security':
356
+ return await this.setMobileSecurity(args);
357
+ case 'snow_push_notification_config':
358
+ return await this.pushNotificationConfig(args);
359
+ case 'snow_deploy_mobile_app':
360
+ return await this.deployMobileApp(args);
361
+ default:
362
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
363
+ }
364
+ });
365
+ }
366
+ catch (error) {
367
+ if (error instanceof types_js_1.McpError)
368
+ throw error;
369
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Tool execution failed: ${error}`);
370
+ }
371
+ });
372
+ }
373
+ // Flow Designer Methods
374
+ async createFlow(args) {
375
+ this.logger.info('Creating flow...', { name: args.name });
376
+ const flowData = {
377
+ name: args.name,
378
+ description: args.description || '',
379
+ application: args.application || 'global',
380
+ active: args.active || false,
381
+ run_as: args.run_as || 'user_who_initiates',
382
+ state: 'draft'
383
+ };
384
+ this.logger.progress('Creating flow in ServiceNow...');
385
+ const response = await this.createRecord('sys_hub_flow', flowData);
386
+ if (!response.success) {
387
+ return this.createResponse(`❌ Failed to create flow: ${response.error}`);
388
+ }
389
+ const result = response.data;
390
+ this.logger.info('✅ Flow created', { sys_id: result.sys_id });
391
+ return this.createResponse(`✅ Flow created successfully!
392
+ 🔄 **${args.name}**
393
+ 📝 ${args.description || 'No description'}
394
+ 🔧 State: Draft
395
+ 🏃 Run as: ${args.run_as || 'User who initiates'}
396
+ 🆔 sys_id: ${result.sys_id}
397
+
398
+ ✨ Flow ready for configuration!`);
399
+ }
400
+ async createFlowAction(args) {
401
+ this.logger.info('Creating flow action...', {
402
+ flow: args.flow,
403
+ action_type: args.action_type
404
+ });
405
+ const actionData = {
406
+ flow: args.flow,
407
+ action_type: args.action_type,
408
+ action_name: args.action_name || args.action_type,
409
+ inputs: JSON.stringify(args.inputs || {}),
410
+ order: args.order || 100
411
+ };
412
+ this.logger.progress('Adding action to flow...');
413
+ const response = await this.createRecord('sys_hub_action_instance', actionData);
414
+ if (!response.success) {
415
+ return this.createResponse(`❌ Failed to create action: ${response.error}`);
416
+ }
417
+ this.logger.info('✅ Flow action created');
418
+ return this.createResponse(`✅ Flow action added!
419
+ ⚡ Type: ${args.action_type}
420
+ 📝 Name: ${args.action_name || args.action_type}
421
+ 📊 Order: ${args.order || 100}
422
+ 🆔 sys_id: ${response.data.sys_id}`);
423
+ }
424
+ async createSubflow(args) {
425
+ this.logger.info('Creating subflow...', { name: args.name });
426
+ const subflowData = {
427
+ name: args.name,
428
+ description: args.description || '',
429
+ inputs: JSON.stringify(args.inputs || []),
430
+ outputs: JSON.stringify(args.outputs || []),
431
+ active: false
432
+ };
433
+ this.logger.progress('Creating subflow...');
434
+ const response = await this.createRecord('sys_hub_sub_flow', subflowData);
435
+ if (!response.success) {
436
+ return this.createResponse(`❌ Failed to create subflow: ${response.error}`);
437
+ }
438
+ this.logger.info('✅ Subflow created');
439
+ return this.createResponse(`✅ Subflow created!
440
+ 🔄 **${args.name}**
441
+ 📥 Inputs: ${args.inputs?.length || 0}
442
+ 📤 Outputs: ${args.outputs?.length || 0}
443
+ 🆔 sys_id: ${response.data.sys_id}`);
444
+ }
445
+ async addFlowTrigger(args) {
446
+ this.logger.info('Adding flow trigger...', {
447
+ flow: args.flow,
448
+ trigger_type: args.trigger_type
449
+ });
450
+ const triggerData = {
451
+ flow: args.flow,
452
+ trigger_type: args.trigger_type,
453
+ active: true
454
+ };
455
+ if (args.trigger_type === 'record') {
456
+ triggerData.table = args.table;
457
+ triggerData.condition = args.condition || '';
458
+ }
459
+ else if (args.trigger_type === 'schedule') {
460
+ triggerData.schedule = args.schedule;
461
+ }
462
+ this.logger.progress('Adding trigger...');
463
+ const response = await this.createRecord('sys_hub_trigger_instance', triggerData);
464
+ if (!response.success) {
465
+ return this.createResponse(`❌ Failed to add trigger: ${response.error}`);
466
+ }
467
+ this.logger.info('✅ Trigger added');
468
+ return this.createResponse(`✅ Flow trigger added!
469
+ ⚡ Type: ${args.trigger_type}
470
+ ${args.table ? `📋 Table: ${args.table}` : ''}
471
+ ${args.schedule ? `⏰ Schedule: ${args.schedule}` : ''}
472
+ 🆔 sys_id: ${response.data.sys_id}`);
473
+ }
474
+ async publishFlow(args) {
475
+ this.logger.info('Publishing flow...', { flow_id: args.flow_id });
476
+ const updateData = {
477
+ active: args.activate !== false,
478
+ state: 'published',
479
+ version: args.version || '1.0'
480
+ };
481
+ this.logger.progress('Publishing flow...');
482
+ const response = await this.updateRecord('sys_hub_flow', args.flow_id, updateData);
483
+ if (!response.success) {
484
+ return this.createResponse(`❌ Failed to publish flow: ${response.error}`);
485
+ }
486
+ this.logger.info('✅ Flow published');
487
+ return this.createResponse(`✅ Flow published!
488
+ 📢 State: Published
489
+ ✅ Active: ${args.activate !== false}
490
+ 🔢 Version: ${args.version || '1.0'}
491
+ 🆔 sys_id: ${args.flow_id}`);
492
+ }
493
+ async testFlow(args) {
494
+ this.logger.info('Testing flow...', { flow_id: args.flow_id });
495
+ const testData = {
496
+ flow: args.flow_id,
497
+ test_data: JSON.stringify(args.test_data || {}),
498
+ debug: args.debug !== false,
499
+ state: 'running'
500
+ };
501
+ this.logger.progress('Executing flow test...');
502
+ const response = await this.createRecord('sys_flow_context', testData);
503
+ if (!response.success) {
504
+ return this.createResponse(`❌ Failed to test flow: ${response.error}`);
505
+ }
506
+ this.logger.info('✅ Flow test initiated');
507
+ return this.createResponse(`✅ Flow test started!
508
+ 🧪 Execution ID: ${response.data.sys_id}
509
+ 🐛 Debug: ${args.debug !== false ? 'Enabled' : 'Disabled'}
510
+ ⏳ Status: Running
511
+
512
+ Check execution details for results.`);
513
+ }
514
+ async getFlowExecutionDetails(args) {
515
+ this.logger.info('Getting flow execution details...');
516
+ let query = '';
517
+ if (args.flow_id)
518
+ query = `flow=${args.flow_id}`;
519
+ if (args.execution_id)
520
+ query = `sys_id=${args.execution_id}`;
521
+ if (args.status)
522
+ query += `^state=${args.status}`;
523
+ this.logger.progress('Retrieving execution history...');
524
+ const response = await this.queryTable('sys_flow_context', query, args.limit || 10);
525
+ if (!response.success) {
526
+ return this.createResponse(`❌ Failed to get executions: ${response.error}`);
527
+ }
528
+ const executions = response.data.result;
529
+ if (!executions.length) {
530
+ return this.createResponse(`❌ No execution history found`);
531
+ }
532
+ this.logger.info(`Found ${executions.length} executions`);
533
+ const executionList = executions.map((exec) => `🔄 **${exec.sys_id}**
534
+ 📊 State: ${exec.state}
535
+ ⏰ Started: ${exec.sys_created_on}
536
+ ⏱️ Duration: ${exec.duration || 'N/A'}`).join('\n\n');
537
+ return this.createResponse(`📊 Flow Execution History:\n\n${executionList}\n\n✨ Total: ${executions.length} execution(s)`);
538
+ }
539
+ // Agent Workspace Methods
540
+ async createWorkspace(args) {
541
+ this.logger.info('Creating agent workspace...', { name: args.name });
542
+ const workspaceData = {
543
+ name: args.name,
544
+ description: args.description || '',
545
+ roles: args.roles?.join(',') || '',
546
+ default_landing_page: args.default_landing_page || '',
547
+ branding: JSON.stringify(args.branding || {}),
548
+ active: false
549
+ };
550
+ this.logger.progress('Creating workspace...');
551
+ const response = await this.createRecord('sys_aw_workspace', workspaceData);
552
+ if (!response.success) {
553
+ return this.createResponse(`❌ Failed to create workspace: ${response.error}`);
554
+ }
555
+ const result = response.data;
556
+ this.logger.info('✅ Workspace created', { sys_id: result.sys_id });
557
+ return this.createResponse(`✅ Agent Workspace created!
558
+ 💼 **${args.name}**
559
+ 📝 ${args.description || 'No description'}
560
+ 👥 Roles: ${args.roles?.join(', ') || 'All'}
561
+ 🆔 sys_id: ${result.sys_id}
562
+
563
+ ✨ Workspace ready for configuration!`);
564
+ }
565
+ async configureWorkspaceTab(args) {
566
+ this.logger.info('Configuring workspace tab...', {
567
+ workspace: args.workspace,
568
+ label: args.label
569
+ });
570
+ const tabData = {
571
+ workspace: args.workspace,
572
+ label: args.label,
573
+ url: args.url || '',
574
+ order: args.order || 100,
575
+ icon: args.icon || ''
576
+ };
577
+ this.logger.progress('Adding tab...');
578
+ const response = await this.createRecord('sys_aw_tab', tabData);
579
+ if (!response.success) {
580
+ return this.createResponse(`❌ Failed to add tab: ${response.error}`);
581
+ }
582
+ this.logger.info('✅ Tab configured');
583
+ return this.createResponse(`✅ Workspace tab added!
584
+ 📑 Label: ${args.label}
585
+ 🔗 URL: ${args.url || 'Default'}
586
+ 📊 Order: ${args.order || 100}
587
+ 🆔 sys_id: ${response.data.sys_id}`);
588
+ }
589
+ async addWorkspaceList(args) {
590
+ this.logger.info('Adding workspace list...', {
591
+ workspace: args.workspace,
592
+ table: args.table
593
+ });
594
+ const listData = {
595
+ workspace: args.workspace,
596
+ table: args.table,
597
+ filter: args.filter || '',
598
+ columns: args.columns?.join(',') || '',
599
+ order_by: args.order_by || ''
600
+ };
601
+ this.logger.progress('Adding list...');
602
+ const response = await this.createRecord('sys_aw_list', listData);
603
+ if (!response.success) {
604
+ return this.createResponse(`❌ Failed to add list: ${response.error}`);
605
+ }
606
+ this.logger.info('✅ List added');
607
+ return this.createResponse(`✅ Workspace list added!
608
+ 📋 Table: ${args.table}
609
+ 🔍 Filter: ${args.filter || 'None'}
610
+ 📊 Columns: ${args.columns?.length || 'Default'}
611
+ 🆔 sys_id: ${response.data.sys_id}`);
612
+ }
613
+ async createWorkspaceForm(args) {
614
+ this.logger.info('Creating workspace form...', {
615
+ workspace: args.workspace,
616
+ table: args.table
617
+ });
618
+ const formData = {
619
+ workspace: args.workspace,
620
+ table: args.table,
621
+ sections: JSON.stringify(args.sections || []),
622
+ fields: args.fields?.join(',') || ''
623
+ };
624
+ this.logger.progress('Creating form...');
625
+ const response = await this.createRecord('sys_aw_form', formData);
626
+ if (!response.success) {
627
+ return this.createResponse(`❌ Failed to create form: ${response.error}`);
628
+ }
629
+ this.logger.info('✅ Form created');
630
+ return this.createResponse(`✅ Workspace form created!
631
+ 📋 Table: ${args.table}
632
+ 📑 Sections: ${args.sections?.length || 0}
633
+ 📝 Fields: ${args.fields?.length || 'Default'}
634
+ 🆔 sys_id: ${response.data.sys_id}`);
635
+ }
636
+ async configureWorkspaceUIAction(args) {
637
+ this.logger.info('Configuring UI action...', {
638
+ workspace: args.workspace,
639
+ name: args.name
640
+ });
641
+ const actionData = {
642
+ workspace: args.workspace,
643
+ name: args.name,
644
+ label: args.label,
645
+ script: args.script || '',
646
+ condition: args.condition || ''
647
+ };
648
+ this.logger.progress('Adding UI action...');
649
+ const response = await this.createRecord('sys_aw_ui_action', actionData);
650
+ if (!response.success) {
651
+ return this.createResponse(`❌ Failed to add UI action: ${response.error}`);
652
+ }
653
+ this.logger.info('✅ UI action configured');
654
+ return this.createResponse(`✅ UI Action added!
655
+ ⚡ Name: ${args.name}
656
+ 🏷️ Label: ${args.label}
657
+ 🔧 Condition: ${args.condition || 'Always'}
658
+ 🆔 sys_id: ${response.data.sys_id}`);
659
+ }
660
+ async deployWorkspace(args) {
661
+ this.logger.info('Deploying workspace...', { workspace_id: args.workspace_id });
662
+ const updateData = {
663
+ active: args.activate !== false,
664
+ roles: args.roles?.join(',') || ''
665
+ };
666
+ this.logger.progress('Deploying workspace...');
667
+ const response = await this.updateRecord('sys_aw_workspace', args.workspace_id, updateData);
668
+ if (!response.success) {
669
+ return this.createResponse(`❌ Failed to deploy workspace: ${response.error}`);
670
+ }
671
+ this.logger.info('✅ Workspace deployed');
672
+ return this.createResponse(`✅ Workspace deployed!
673
+ ✅ Active: ${args.activate !== false}
674
+ 👥 Available to: ${args.roles?.join(', ') || 'All roles'}
675
+ 🆔 sys_id: ${args.workspace_id}
676
+
677
+ ✨ Agents can now access this workspace!`);
678
+ }
679
+ // Mobile Platform Methods
680
+ async createMobileAppConfig(args) {
681
+ this.logger.info('Creating mobile app config...', {
682
+ name: args.name,
683
+ app_id: args.app_id
684
+ });
685
+ const configData = {
686
+ name: args.name,
687
+ description: args.description || '',
688
+ app_id: args.app_id,
689
+ version: args.version || '1.0.0',
690
+ platforms: args.platforms?.join(',') || 'ios,android',
691
+ active: false
692
+ };
693
+ this.logger.progress('Creating app configuration...');
694
+ const response = await this.createRecord('sys_mobile_config', configData);
695
+ if (!response.success) {
696
+ return this.createResponse(`❌ Failed to create app config: ${response.error}`);
697
+ }
698
+ const result = response.data;
699
+ this.logger.info('✅ Mobile app config created', { sys_id: result.sys_id });
700
+ return this.createResponse(`✅ Mobile App configured!
701
+ 📱 **${args.name}**
702
+ 🔖 App ID: ${args.app_id}
703
+ 📦 Version: ${args.version || '1.0.0'}
704
+ 🖥️ Platforms: ${args.platforms?.join(', ') || 'iOS, Android'}
705
+ 🆔 sys_id: ${result.sys_id}
706
+
707
+ ✨ App ready for configuration!`);
708
+ }
709
+ async configureMobileLayout(args) {
710
+ this.logger.info('Configuring mobile layout...', {
711
+ app_config: args.app_config,
712
+ type: args.type
713
+ });
714
+ const layoutData = {
715
+ app_config: args.app_config,
716
+ name: args.name,
717
+ type: args.type,
718
+ components: JSON.stringify(args.components || [])
719
+ };
720
+ this.logger.progress('Creating layout...');
721
+ const response = await this.createRecord('sys_mobile_layout', layoutData);
722
+ if (!response.success) {
723
+ return this.createResponse(`❌ Failed to create layout: ${response.error}`);
724
+ }
725
+ this.logger.info('✅ Layout configured');
726
+ return this.createResponse(`✅ Mobile layout created!
727
+ 📐 Name: ${args.name}
728
+ 🎨 Type: ${args.type}
729
+ 🧩 Components: ${args.components?.length || 0}
730
+ 🆔 sys_id: ${response.data.sys_id}`);
731
+ }
732
+ async createMobileApplet(args) {
733
+ this.logger.info('Creating mobile applet...', { name: args.name });
734
+ const appletData = {
735
+ name: args.name,
736
+ table: args.table,
737
+ layout: args.layout || '',
738
+ icon: args.icon || '',
739
+ order: args.order || 100
740
+ };
741
+ this.logger.progress('Creating applet...');
742
+ const response = await this.createRecord('sys_mobile_applet', appletData);
743
+ if (!response.success) {
744
+ return this.createResponse(`❌ Failed to create applet: ${response.error}`);
745
+ }
746
+ this.logger.info('✅ Applet created');
747
+ return this.createResponse(`✅ Mobile applet created!
748
+ 📲 Name: ${args.name}
749
+ 📋 Table: ${args.table}
750
+ 🎨 Icon: ${args.icon || 'Default'}
751
+ 📊 Order: ${args.order || 100}
752
+ 🆔 sys_id: ${response.data.sys_id}`);
753
+ }
754
+ async configureOfflineTables(args) {
755
+ this.logger.info('Configuring offline tables...', {
756
+ app_config: args.app_config,
757
+ tables: args.tables
758
+ });
759
+ const offlineData = {
760
+ app_config: args.app_config,
761
+ tables: args.tables.join(','),
762
+ sync_rules: JSON.stringify(args.sync_rules || {}),
763
+ frequency: args.frequency || 'on_demand'
764
+ };
765
+ this.logger.progress('Configuring offline sync...');
766
+ const response = await this.createRecord('sys_mobile_offline', offlineData);
767
+ if (!response.success) {
768
+ return this.createResponse(`❌ Failed to configure offline: ${response.error}`);
769
+ }
770
+ this.logger.info('✅ Offline sync configured');
771
+ return this.createResponse(`✅ Offline sync configured!
772
+ 📋 Tables: ${args.tables.join(', ')}
773
+ 🔄 Frequency: ${args.frequency || 'On demand'}
774
+ 🆔 sys_id: ${response.data.sys_id}`);
775
+ }
776
+ async setMobileSecurity(args) {
777
+ this.logger.info('Setting mobile security...', { app_config: args.app_config });
778
+ const securityData = {
779
+ app_config: args.app_config,
780
+ require_pin: args.require_pin !== false,
781
+ biometric_auth: args.biometric_auth || false,
782
+ session_timeout: args.session_timeout || 30,
783
+ data_encryption: args.data_encryption !== false
784
+ };
785
+ this.logger.progress('Applying security settings...');
786
+ const response = await this.createRecord('sys_mobile_security', securityData);
787
+ if (!response.success) {
788
+ return this.createResponse(`❌ Failed to set security: ${response.error}`);
789
+ }
790
+ this.logger.info('✅ Security configured');
791
+ return this.createResponse(`✅ Mobile security configured!
792
+ 🔐 PIN Required: ${args.require_pin !== false}
793
+ 👆 Biometric: ${args.biometric_auth || false}
794
+ ⏱️ Timeout: ${args.session_timeout || 30} minutes
795
+ 🔒 Encryption: ${args.data_encryption !== false}
796
+ 🆔 sys_id: ${response.data.sys_id}`);
797
+ }
798
+ async pushNotificationConfig(args) {
799
+ this.logger.info('Configuring push notifications...', { app_config: args.app_config });
800
+ const notifData = {
801
+ app_config: args.app_config,
802
+ event_types: args.event_types.join(','),
803
+ templates: JSON.stringify(args.templates || {}),
804
+ enabled: args.enabled !== false
805
+ };
806
+ this.logger.progress('Setting up notifications...');
807
+ const response = await this.createRecord('sys_push_notification', notifData);
808
+ if (!response.success) {
809
+ return this.createResponse(`❌ Failed to configure notifications: ${response.error}`);
810
+ }
811
+ this.logger.info('✅ Push notifications configured');
812
+ return this.createResponse(`✅ Push notifications configured!
813
+ 🔔 Events: ${args.event_types.join(', ')}
814
+ ✅ Enabled: ${args.enabled !== false}
815
+ 🆔 sys_id: ${response.data.sys_id}`);
816
+ }
817
+ async deployMobileApp(args) {
818
+ this.logger.info('Deploying mobile app...', {
819
+ app_config_id: args.app_config_id,
820
+ environment: args.environment
821
+ });
822
+ const deployData = {
823
+ app_config: args.app_config_id,
824
+ environment: args.environment,
825
+ deploy_to_stores: args.deploy_to_stores || false,
826
+ release_notes: args.release_notes || '',
827
+ deployment_date: new Date().toISOString()
828
+ };
829
+ this.logger.progress('Deploying app...');
830
+ const response = await this.createRecord('sys_mobile_deployment', deployData);
831
+ if (!response.success) {
832
+ return this.createResponse(`❌ Failed to deploy app: ${response.error}`);
833
+ }
834
+ // Update app config to active
835
+ await this.updateRecord('sys_mobile_config', args.app_config_id, { active: true });
836
+ this.logger.info('✅ Mobile app deployed');
837
+ return this.createResponse(`✅ Mobile app deployed!
838
+ 🚀 Environment: ${args.environment}
839
+ 📱 Store Deployment: ${args.deploy_to_stores ? 'Yes' : 'No'}
840
+ 📝 Release Notes: ${args.release_notes || 'None'}
841
+ 🆔 Deployment ID: ${response.data.sys_id}
842
+
843
+ ✨ App is now live in ${args.environment}!`);
844
+ }
845
+ async start() {
846
+ const transport = new stdio_js_1.StdioServerTransport();
847
+ await this.server.connect(transport);
848
+ // Log ready state
849
+ this.logger.info('🚀 ServiceNow Flow, Workspace & Mobile MCP Server (Enhanced) running');
850
+ this.logger.info('📊 Token tracking enabled');
851
+ this.logger.info('⏳ Progress indicators active');
852
+ }
853
+ }
854
+ // Start the enhanced server
855
+ const server = new ServiceNowFlowWorkspaceMobileMCPEnhanced();
856
+ server.start().catch((error) => {
857
+ console.error('Failed to start enhanced server:', error);
858
+ process.exit(1);
859
+ });
860
+ //# sourceMappingURL=servicenow-flow-workspace-mobile-mcp-enhanced.js.map