snow-flow 4.5.2 → 4.5.5

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.
@@ -275,6 +275,395 @@ class ServiceNowFlowWorkspaceMobileMCP {
275
275
  required: ['table']
276
276
  }
277
277
  },
278
+ // ==========================================
279
+ // UI BUILDER TOOLS - COMPLETE NOW EXPERIENCE FRAMEWORK INTEGRATION
280
+ // Official ServiceNow sys_ux_* APIs for conversational UI Builder development
281
+ // ==========================================
282
+ // UI Builder Page Management (sys_ux_page)
283
+ {
284
+ name: 'snow_create_uib_page',
285
+ description: 'Creates a new UI Builder page in the Now Experience Framework using official ServiceNow sys_ux_page API. Enables conversational page creation with full UXF integration.',
286
+ inputSchema: {
287
+ type: 'object',
288
+ properties: {
289
+ name: { type: 'string', description: 'Page name (must be unique)' },
290
+ title: { type: 'string', description: 'Page title displayed in browser' },
291
+ route: { type: 'string', description: 'URL route for the page (e.g., /my-dashboard)' },
292
+ description: { type: 'string', description: 'Page description' },
293
+ application: { type: 'string', description: 'Application scope', default: 'global' },
294
+ theme: { type: 'string', description: 'Page theme', default: 'standard' },
295
+ public_read: { type: 'boolean', description: 'Allow public read access', default: false },
296
+ layout_type: { type: 'string', enum: ['container', 'grid', 'flex'], description: 'Page layout type', default: 'container' },
297
+ responsive: { type: 'boolean', description: 'Enable responsive design', default: true },
298
+ active: { type: 'boolean', description: 'Page is active', default: true }
299
+ },
300
+ required: ['name', 'title', 'route']
301
+ }
302
+ },
303
+ {
304
+ name: 'snow_update_uib_page',
305
+ description: 'Updates an existing UI Builder page configuration, metadata, or settings.',
306
+ inputSchema: {
307
+ type: 'object',
308
+ properties: {
309
+ page_id: { type: 'string', description: 'Page sys_id to update' },
310
+ title: { type: 'string', description: 'New page title' },
311
+ route: { type: 'string', description: 'New URL route' },
312
+ description: { type: 'string', description: 'New description' },
313
+ theme: { type: 'string', description: 'New page theme' },
314
+ layout_type: { type: 'string', enum: ['container', 'grid', 'flex'], description: 'New layout type' },
315
+ responsive: { type: 'boolean', description: 'Enable/disable responsive design' },
316
+ active: { type: 'boolean', description: 'Page active status' }
317
+ },
318
+ required: ['page_id']
319
+ }
320
+ },
321
+ {
322
+ name: 'snow_delete_uib_page',
323
+ description: 'Safely deletes a UI Builder page and all associated elements, with comprehensive dependency validation.',
324
+ inputSchema: {
325
+ type: 'object',
326
+ properties: {
327
+ page_id: { type: 'string', description: 'Page sys_id to delete' },
328
+ force_delete: { type: 'boolean', description: 'Force delete even if dependencies exist', default: false },
329
+ backup_before_delete: { type: 'boolean', description: 'Create backup before deletion', default: true },
330
+ clean_orphaned_elements: { type: 'boolean', description: 'Clean up orphaned page elements', default: true }
331
+ },
332
+ required: ['page_id']
333
+ }
334
+ },
335
+ {
336
+ name: 'snow_discover_uib_pages',
337
+ description: 'Discovers all UI Builder pages in the instance with advanced filtering and relationship analysis.',
338
+ inputSchema: {
339
+ type: 'object',
340
+ properties: {
341
+ application: { type: 'string', description: 'Filter by application scope' },
342
+ active_only: { type: 'boolean', description: 'Show only active pages', default: true },
343
+ include_elements: { type: 'boolean', description: 'Include page elements and layout', default: false },
344
+ include_data_brokers: { type: 'boolean', description: 'Include data broker configurations', default: false },
345
+ include_routing: { type: 'boolean', description: 'Include page registry routing info', default: false },
346
+ name_filter: { type: 'string', description: 'Filter pages by name (partial match)' },
347
+ route_filter: { type: 'string', description: 'Filter pages by route pattern' },
348
+ theme_filter: { type: 'string', description: 'Filter pages by theme' },
349
+ limit: { type: 'number', description: 'Maximum pages to return', default: 50 }
350
+ }
351
+ }
352
+ },
353
+ // UI Builder Component Library Management (sys_ux_lib_*)
354
+ {
355
+ name: 'snow_create_uib_component',
356
+ description: 'Creates a custom UI Builder component using official ServiceNow sys_ux_lib_component and sys_ux_lib_source_script APIs.',
357
+ inputSchema: {
358
+ type: 'object',
359
+ properties: {
360
+ name: { type: 'string', description: 'Component name (must be unique, kebab-case recommended)' },
361
+ label: { type: 'string', description: 'Component display label' },
362
+ description: { type: 'string', description: 'Component description and usage notes' },
363
+ category: { type: 'string', description: 'Component category for organization', default: 'custom' },
364
+ source_script: { type: 'string', description: 'Component source code (JavaScript/React/Web Components)' },
365
+ properties_schema: { type: 'object', description: 'Component properties schema definition (JSON Schema)' },
366
+ events: { type: 'array', items: { type: 'string' }, description: 'Events this component can emit' },
367
+ dependencies: { type: 'array', items: { type: 'string' }, description: 'External dependencies (libraries, other components)' },
368
+ styling: { type: 'object', description: 'Default styling and CSS configuration' },
369
+ version: { type: 'string', description: 'Component version', default: '1.0.0' },
370
+ tags: { type: 'array', items: { type: 'string' }, description: 'Tags for component discovery' }
371
+ },
372
+ required: ['name', 'label', 'source_script']
373
+ }
374
+ },
375
+ {
376
+ name: 'snow_update_uib_component',
377
+ description: 'Updates an existing UI Builder component definition, source code, or configuration.',
378
+ inputSchema: {
379
+ type: 'object',
380
+ properties: {
381
+ component_id: { type: 'string', description: 'Component sys_id to update' },
382
+ label: { type: 'string', description: 'New component label' },
383
+ description: { type: 'string', description: 'New description' },
384
+ source_script: { type: 'string', description: 'Updated component source code' },
385
+ properties_schema: { type: 'object', description: 'Updated properties schema' },
386
+ styling: { type: 'object', description: 'Updated styling configuration' },
387
+ version: { type: 'string', description: 'New version number (semantic versioning)' },
388
+ events: { type: 'array', items: { type: 'string' }, description: 'Updated events list' },
389
+ dependencies: { type: 'array', items: { type: 'string' }, description: 'Updated dependencies' },
390
+ active: { type: 'boolean', description: 'Component active status' }
391
+ },
392
+ required: ['component_id']
393
+ }
394
+ },
395
+ {
396
+ name: 'snow_discover_uib_components',
397
+ description: 'Discovers all available UI Builder components including ServiceNow built-in and custom components with comprehensive metadata.',
398
+ inputSchema: {
399
+ type: 'object',
400
+ properties: {
401
+ category: { type: 'string', description: 'Filter by component category (layout, input, display, custom)' },
402
+ custom_only: { type: 'boolean', description: 'Show only custom components', default: false },
403
+ built_in_only: { type: 'boolean', description: 'Show only ServiceNow built-in components', default: false },
404
+ include_source: { type: 'boolean', description: 'Include component source code', default: false },
405
+ include_usage_stats: { type: 'boolean', description: 'Include component usage statistics across pages', default: false },
406
+ include_dependencies: { type: 'boolean', description: 'Include component dependency information', default: false },
407
+ name_filter: { type: 'string', description: 'Filter components by name or label' },
408
+ version_filter: { type: 'string', description: 'Filter by version pattern' },
409
+ application: { type: 'string', description: 'Filter by application scope' },
410
+ limit: { type: 'number', description: 'Maximum components to return', default: 100 }
411
+ }
412
+ }
413
+ },
414
+ {
415
+ name: 'snow_clone_uib_component',
416
+ description: 'Clones an existing UI Builder component to create a customized variant with modifications.',
417
+ inputSchema: {
418
+ type: 'object',
419
+ properties: {
420
+ source_component_id: { type: 'string', description: 'Source component sys_id to clone' },
421
+ new_name: { type: 'string', description: 'Name for the cloned component' },
422
+ new_label: { type: 'string', description: 'Label for the cloned component' },
423
+ modifications: { type: 'object', description: 'Specific modifications to apply to cloned component' },
424
+ category: { type: 'string', description: 'Category for cloned component', default: 'custom' },
425
+ version: { type: 'string', description: 'Version for cloned component', default: '1.0.0' },
426
+ description: { type: 'string', description: 'Description of clone purpose and changes' }
427
+ },
428
+ required: ['source_component_id', 'new_name', 'new_label']
429
+ }
430
+ },
431
+ // UI Builder Data Broker Management (sys_ux_data_broker)
432
+ {
433
+ name: 'snow_create_uib_data_broker',
434
+ description: 'Creates a UI Builder data broker for connecting pages to ServiceNow data sources using official sys_ux_data_broker API.',
435
+ inputSchema: {
436
+ type: 'object',
437
+ properties: {
438
+ name: { type: 'string', description: 'Data broker name (must be unique)' },
439
+ label: { type: 'string', description: 'Data broker display label' },
440
+ table: { type: 'string', description: 'ServiceNow table to connect' },
441
+ type: { type: 'string', enum: ['table', 'script', 'rest_message'], description: 'Data broker type', default: 'table' },
442
+ query: { type: 'string', description: 'Default query for table data broker' },
443
+ script: { type: 'string', description: 'Script for script-based data broker' },
444
+ rest_message: { type: 'string', description: 'REST message sys_id for REST data broker' },
445
+ fields: { type: 'array', items: { type: 'string' }, description: 'Fields to retrieve (leave empty for all)' },
446
+ auto_refresh: { type: 'boolean', description: 'Enable automatic data refresh', default: false },
447
+ refresh_interval: { type: 'number', description: 'Refresh interval in seconds', default: 30 },
448
+ cache_duration: { type: 'number', description: 'Cache duration in seconds', default: 300 },
449
+ max_records: { type: 'number', description: 'Maximum records to fetch', default: 1000 }
450
+ },
451
+ required: ['name', 'label', 'type']
452
+ }
453
+ },
454
+ {
455
+ name: 'snow_configure_uib_data_broker',
456
+ description: 'Configures or updates an existing UI Builder data broker with new query, fields, or performance settings.',
457
+ inputSchema: {
458
+ type: 'object',
459
+ properties: {
460
+ broker_id: { type: 'string', description: 'Data broker sys_id' },
461
+ query: { type: 'string', description: 'Updated query condition' },
462
+ fields: { type: 'array', items: { type: 'string' }, description: 'Updated fields list' },
463
+ auto_refresh: { type: 'boolean', description: 'Enable/disable auto-refresh' },
464
+ refresh_interval: { type: 'number', description: 'New refresh interval in seconds' },
465
+ cache_duration: { type: 'number', description: 'New cache duration in seconds' },
466
+ max_records: { type: 'number', description: 'New maximum records limit' },
467
+ active: { type: 'boolean', description: 'Data broker active status' }
468
+ },
469
+ required: ['broker_id']
470
+ }
471
+ },
472
+ // UI Builder Page Layout Management (sys_ux_page_element)
473
+ {
474
+ name: 'snow_add_uib_page_element',
475
+ description: 'Adds a component element to a UI Builder page using official sys_ux_page_element API with full layout control.',
476
+ inputSchema: {
477
+ type: 'object',
478
+ properties: {
479
+ page_id: { type: 'string', description: 'Target page sys_id' },
480
+ component: { type: 'string', description: 'Component name or sys_id from component library' },
481
+ container_id: { type: 'string', description: 'Parent container element ID (optional for root level)' },
482
+ position: { type: 'number', description: 'Element position in container', default: 0 },
483
+ properties: { type: 'object', description: 'Component properties and configuration' },
484
+ data_broker: { type: 'string', description: 'Data broker sys_id to bind to component' },
485
+ responsive_config: { type: 'object', description: 'Responsive layout configuration for different screen sizes' },
486
+ conditional_display: { type: 'string', description: 'Condition script for element visibility' },
487
+ css_classes: { type: 'array', items: { type: 'string' }, description: 'CSS classes to apply' },
488
+ inline_styles: { type: 'object', description: 'Inline styles configuration' }
489
+ },
490
+ required: ['page_id', 'component']
491
+ }
492
+ },
493
+ {
494
+ name: 'snow_update_uib_page_element',
495
+ description: 'Updates properties, position, or configuration of an existing UI Builder page element.',
496
+ inputSchema: {
497
+ type: 'object',
498
+ properties: {
499
+ element_id: { type: 'string', description: 'Page element sys_id' },
500
+ properties: { type: 'object', description: 'Updated component properties' },
501
+ position: { type: 'number', description: 'New position in container' },
502
+ data_broker: { type: 'string', description: 'New data broker binding' },
503
+ responsive_config: { type: 'object', description: 'Updated responsive configuration' },
504
+ conditional_display: { type: 'string', description: 'Updated display condition' },
505
+ css_classes: { type: 'array', items: { type: 'string' }, description: 'Updated CSS classes' },
506
+ inline_styles: { type: 'object', description: 'Updated inline styles' }
507
+ },
508
+ required: ['element_id']
509
+ }
510
+ },
511
+ {
512
+ name: 'snow_remove_uib_page_element',
513
+ description: 'Removes a component element from a UI Builder page with comprehensive dependency validation.',
514
+ inputSchema: {
515
+ type: 'object',
516
+ properties: {
517
+ element_id: { type: 'string', description: 'Page element sys_id to remove' },
518
+ validate_dependencies: { type: 'boolean', description: 'Check for element dependencies before removal', default: true },
519
+ cleanup_orphaned_data: { type: 'boolean', description: 'Clean up orphaned data brokers and scripts', default: true }
520
+ },
521
+ required: ['element_id']
522
+ }
523
+ },
524
+ // UI Builder Page Registry & Routing (sys_ux_page_registry)
525
+ {
526
+ name: 'snow_create_uib_page_registry',
527
+ description: 'Creates URL routing configuration for UI Builder page using official sys_ux_page_registry API.',
528
+ inputSchema: {
529
+ type: 'object',
530
+ properties: {
531
+ page_id: { type: 'string', description: 'Target page sys_id' },
532
+ path: { type: 'string', description: 'URL path pattern (e.g., /dashboard, /incidents/:id)' },
533
+ application: { type: 'string', description: 'Application scope for routing' },
534
+ roles: { type: 'array', items: { type: 'string' }, description: 'Roles required to access page' },
535
+ public_access: { type: 'boolean', description: 'Allow public access without authentication', default: false },
536
+ redirect_url: { type: 'string', description: 'Redirect URL for unauthorized access' },
537
+ meta_title: { type: 'string', description: 'SEO meta title for the page' },
538
+ meta_description: { type: 'string', description: 'SEO meta description' },
539
+ parameter_mapping: { type: 'object', description: 'URL parameter mapping configuration' },
540
+ cache_control: { type: 'string', description: 'Cache control headers' }
541
+ },
542
+ required: ['page_id', 'path']
543
+ }
544
+ },
545
+ {
546
+ name: 'snow_discover_uib_routes',
547
+ description: 'Discovers all UI Builder page routes and their security/access configurations.',
548
+ inputSchema: {
549
+ type: 'object',
550
+ properties: {
551
+ application: { type: 'string', description: 'Filter by application scope' },
552
+ active_only: { type: 'boolean', description: 'Show only active routes', default: true },
553
+ include_security: { type: 'boolean', description: 'Include role and security information', default: false },
554
+ include_parameters: { type: 'boolean', description: 'Include URL parameter configurations', default: false },
555
+ path_pattern: { type: 'string', description: 'Filter by path pattern or wildcard' },
556
+ role_filter: { type: 'string', description: 'Filter by required role' }
557
+ }
558
+ }
559
+ },
560
+ // UI Builder Client Script Management (sys_ux_client_script)
561
+ {
562
+ name: 'snow_create_uib_client_script',
563
+ description: 'Creates client-side scripts for UI Builder pages using official sys_ux_client_script API.',
564
+ inputSchema: {
565
+ type: 'object',
566
+ properties: {
567
+ page_id: { type: 'string', description: 'Target page sys_id' },
568
+ name: { type: 'string', description: 'Script name (must be unique within page)' },
569
+ type: { type: 'string', enum: ['onLoad', 'onChange', 'onClick', 'onSubmit', 'custom'], description: 'Script trigger type' },
570
+ script: { type: 'string', description: 'JavaScript code for the script' },
571
+ component_reference: { type: 'string', description: 'Reference to specific component if applicable' },
572
+ event_name: { type: 'string', description: 'Custom event name for custom type scripts' },
573
+ execution_order: { type: 'number', description: 'Script execution order', default: 100 },
574
+ async_execution: { type: 'boolean', description: 'Enable async execution', default: false },
575
+ error_handling: { type: 'string', description: 'Error handling strategy', default: 'log' },
576
+ active: { type: 'boolean', description: 'Script is active', default: true }
577
+ },
578
+ required: ['page_id', 'name', 'type', 'script']
579
+ }
580
+ },
581
+ {
582
+ name: 'snow_create_uib_client_state',
583
+ description: 'Creates client state management configuration for UI Builder pages using official sys_ux_client_state API.',
584
+ inputSchema: {
585
+ type: 'object',
586
+ properties: {
587
+ page_id: { type: 'string', description: 'Target page sys_id' },
588
+ state_name: { type: 'string', description: 'State variable name' },
589
+ initial_value: { type: 'string', description: 'Initial state value (JSON format)' },
590
+ scope: { type: 'string', enum: ['page', 'session', 'global'], description: 'State scope', default: 'page' },
591
+ persistent: { type: 'boolean', description: 'Persist state across browser sessions', default: false },
592
+ reactive: { type: 'boolean', description: 'Enable reactive updates', default: true },
593
+ validation_schema: { type: 'object', description: 'State validation schema' },
594
+ description: { type: 'string', description: 'State variable description' }
595
+ },
596
+ required: ['page_id', 'state_name', 'initial_value']
597
+ }
598
+ },
599
+ // UI Builder Event Management (sys_ux_event)
600
+ {
601
+ name: 'snow_create_uib_event',
602
+ description: 'Creates custom events for UI Builder components using official sys_ux_event API.',
603
+ inputSchema: {
604
+ type: 'object',
605
+ properties: {
606
+ name: { type: 'string', description: 'Event name (must be unique)' },
607
+ label: { type: 'string', description: 'Event display label' },
608
+ description: { type: 'string', description: 'Event description and usage' },
609
+ payload_schema: { type: 'object', description: 'Event payload schema definition (JSON Schema)' },
610
+ component_scope: { type: 'string', description: 'Component scope for event availability' },
611
+ global_event: { type: 'boolean', description: 'Global event accessible across all pages', default: false },
612
+ bubbles: { type: 'boolean', description: 'Event bubbles up DOM tree', default: true },
613
+ cancelable: { type: 'boolean', description: 'Event can be cancelled', default: true }
614
+ },
615
+ required: ['name', 'label']
616
+ }
617
+ },
618
+ // UI Builder Validation & Analytics
619
+ {
620
+ name: 'snow_analyze_uib_page_performance',
621
+ description: 'Analyzes UI Builder page performance including load times, component efficiency, and optimization recommendations.',
622
+ inputSchema: {
623
+ type: 'object',
624
+ properties: {
625
+ page_id: { type: 'string', description: 'Page sys_id to analyze' },
626
+ include_components: { type: 'boolean', description: 'Include component-level performance analysis', default: true },
627
+ include_data_broker_stats: { type: 'boolean', description: 'Include data broker performance metrics', default: true },
628
+ include_client_scripts: { type: 'boolean', description: 'Include client script performance', default: true },
629
+ time_period_days: { type: 'number', description: 'Analysis period in days', default: 30 },
630
+ detailed_analysis: { type: 'boolean', description: 'Generate detailed performance report', default: false }
631
+ },
632
+ required: ['page_id']
633
+ }
634
+ },
635
+ {
636
+ name: 'snow_validate_uib_page_structure',
637
+ description: 'Validates UI Builder page structure, component relationships, data flow integrity, and best practices compliance.',
638
+ inputSchema: {
639
+ type: 'object',
640
+ properties: {
641
+ page_id: { type: 'string', description: 'Page sys_id to validate' },
642
+ check_data_brokers: { type: 'boolean', description: 'Validate data broker connections and queries', default: true },
643
+ check_component_dependencies: { type: 'boolean', description: 'Check component dependencies and compatibility', default: true },
644
+ check_routing: { type: 'boolean', description: 'Validate page routing and URL configuration', default: true },
645
+ check_security: { type: 'boolean', description: 'Validate security, ACLs, and access controls', default: true },
646
+ check_performance: { type: 'boolean', description: 'Check for performance best practices', default: true },
647
+ check_accessibility: { type: 'boolean', description: 'Validate accessibility compliance', default: false }
648
+ },
649
+ required: ['page_id']
650
+ }
651
+ },
652
+ {
653
+ name: 'snow_discover_uib_page_usage',
654
+ description: 'Analyzes UI Builder page usage patterns, user interactions, and component effectiveness.',
655
+ inputSchema: {
656
+ type: 'object',
657
+ properties: {
658
+ page_id: { type: 'string', description: 'Page sys_id to analyze usage for' },
659
+ time_period_days: { type: 'number', description: 'Analysis period in days', default: 30 },
660
+ include_user_journeys: { type: 'boolean', description: 'Include user journey analysis', default: false },
661
+ include_conversion_rates: { type: 'boolean', description: 'Include conversion and engagement rates', default: false },
662
+ group_by_role: { type: 'boolean', description: 'Group analytics by user role', default: false }
663
+ },
664
+ required: ['page_id']
665
+ }
666
+ },
278
667
  {
279
668
  name: 'snow_create_mobile_action',
280
669
  description: 'Creates custom actions for mobile app interfaces.',
@@ -380,6 +769,77 @@ class ServiceNowFlowWorkspaceMobileMCP {
380
769
  case 'snow_configure_offline_sync':
381
770
  result = await this.configureOfflineSync(args);
382
771
  break;
772
+ // UI Builder Page Management
773
+ case 'snow_create_uib_page':
774
+ result = await this.createUIBPage(args);
775
+ break;
776
+ case 'snow_update_uib_page':
777
+ result = await this.updateUIBPage(args);
778
+ break;
779
+ case 'snow_delete_uib_page':
780
+ result = await this.deleteUIBPage(args);
781
+ break;
782
+ case 'snow_discover_uib_pages':
783
+ result = await this.discoverUIBPages(args);
784
+ break;
785
+ // UI Builder Component Management
786
+ case 'snow_create_uib_component':
787
+ result = await this.createUIBComponent(args);
788
+ break;
789
+ case 'snow_update_uib_component':
790
+ result = await this.updateUIBComponent(args);
791
+ break;
792
+ case 'snow_discover_uib_components':
793
+ result = await this.discoverUIBComponents(args);
794
+ break;
795
+ case 'snow_clone_uib_component':
796
+ result = await this.cloneUIBComponent(args);
797
+ break;
798
+ // UI Builder Data Broker Management
799
+ case 'snow_create_uib_data_broker':
800
+ result = await this.createUIBDataBroker(args);
801
+ break;
802
+ case 'snow_configure_uib_data_broker':
803
+ result = await this.configureUIBDataBroker(args);
804
+ break;
805
+ // UI Builder Page Layout Management
806
+ case 'snow_add_uib_page_element':
807
+ result = await this.addUIBPageElement(args);
808
+ break;
809
+ case 'snow_update_uib_page_element':
810
+ result = await this.updateUIBPageElement(args);
811
+ break;
812
+ case 'snow_remove_uib_page_element':
813
+ result = await this.removeUIBPageElement(args);
814
+ break;
815
+ // UI Builder Page Registry & Routing
816
+ case 'snow_create_uib_page_registry':
817
+ result = await this.createUIBPageRegistry(args);
818
+ break;
819
+ case 'snow_discover_uib_routes':
820
+ result = await this.discoverUIBRoutes(args);
821
+ break;
822
+ // UI Builder Client Script Management
823
+ case 'snow_create_uib_client_script':
824
+ result = await this.createUIBClientScript(args);
825
+ break;
826
+ case 'snow_create_uib_client_state':
827
+ result = await this.createUIBClientState(args);
828
+ break;
829
+ // UI Builder Event Management
830
+ case 'snow_create_uib_event':
831
+ result = await this.createUIBEvent(args);
832
+ break;
833
+ // UI Builder Validation & Analytics
834
+ case 'snow_analyze_uib_page_performance':
835
+ result = await this.analyzeUIBPagePerformance(args);
836
+ break;
837
+ case 'snow_validate_uib_page_structure':
838
+ result = await this.validateUIBPageStructure(args);
839
+ break;
840
+ case 'snow_discover_uib_page_usage':
841
+ result = await this.discoverUIBPageUsage(args);
842
+ break;
383
843
  case 'snow_create_mobile_action':
384
844
  result = await this.createMobileAction(args);
385
845
  break;
@@ -811,18 +1271,43 @@ ${executionList}
811
1271
  // Agent Workspace Implementation
812
1272
  async createWorkspace(args) {
813
1273
  try {
814
- this.logger.info('Creating workspace...');
1274
+ this.logger.info('Creating Agent Workspace...');
1275
+ // First validate Agent Workspace table access
1276
+ const tableCheck = await this.client.searchRecords('sys_aw_master_config', '', 1);
1277
+ if (!tableCheck.success) {
1278
+ return {
1279
+ success: false,
1280
+ error: 'Agent Workspace tables not accessible. This feature requires ServiceNow Agent Workspace plugin to be installed and activated.',
1281
+ suggestion: 'Install Agent Workspace plugin: System Applications → All Available Applications → Search for "Agent Workspace"'
1282
+ };
1283
+ }
815
1284
  const workspaceData = {
816
1285
  name: args.name,
817
1286
  description: args.description || '',
818
- tables: args.tables.join(','),
1287
+ tables: args.tables ? args.tables.join(',') : '',
819
1288
  home_page: args.home_page || '',
820
1289
  theme: args.theme || 'default',
821
- roles: args.roles ? args.roles.join(',') : ''
1290
+ roles: args.roles ? args.roles.join(',') : '',
1291
+ active: true
822
1292
  };
823
- this.logger.trackAPICall('CREATE', 'sys_aw_workspace', 1);
824
- const response = await this.client.createRecord('sys_aw_workspace', workspaceData);
1293
+ this.logger.trackAPICall('CREATE', 'sys_aw_master_config', 1);
1294
+ const response = await this.client.createRecord('sys_aw_master_config', workspaceData);
825
1295
  if (!response.success) {
1296
+ // Provide specific error guidance
1297
+ if (response.error?.includes('403') || response.error?.includes('Forbidden')) {
1298
+ return {
1299
+ success: false,
1300
+ error: 'Insufficient permissions to create Agent Workspace. Requires workspace_admin role or elevated permissions.',
1301
+ suggestion: 'Contact your ServiceNow administrator to grant Agent Workspace permissions.'
1302
+ };
1303
+ }
1304
+ if (response.error?.includes('400') || response.error?.includes('Bad Request')) {
1305
+ return {
1306
+ success: false,
1307
+ error: 'Invalid workspace configuration. Agent Workspace may not be properly configured in this instance.',
1308
+ suggestion: 'Verify Agent Workspace is enabled and configured. Check System Properties > Agent Workspace settings.'
1309
+ };
1310
+ }
826
1311
  throw new Error(`Failed to create workspace: ${response.error}`);
827
1312
  }
828
1313
  return {
@@ -968,7 +1453,7 @@ ${args.filter ? `🔍 Filter: ${args.filter}` : ''}
968
1453
  const response = await this.client.createRecord('sys_aw_notification_config', notificationData);
969
1454
  if (!response.success) {
970
1455
  // Fallback to updating workspace
971
- await this.client.updateRecord('sys_aw_workspace', args.workspace, {
1456
+ await this.client.updateRecord('sys_aw_master_config', args.workspace, {
972
1457
  notifications_enabled: args.enable_desktop || args.enable_sound
973
1458
  });
974
1459
  }
@@ -994,10 +1479,15 @@ ${args.filter ? `🔍 Filter: ${args.filter}` : ''}
994
1479
  }
995
1480
  async discoverWorkspaces(args) {
996
1481
  try {
997
- this.logger.info('Discovering workspaces...');
998
- const response = await this.client.searchRecords('sys_aw_workspace', '', 50);
1482
+ this.logger.info('Discovering Agent Workspaces...');
1483
+ // Validate table access first
1484
+ const response = await this.client.searchRecords('sys_aw_master_config', '', 50);
999
1485
  if (!response.success) {
1000
- throw new Error('Failed to discover workspaces');
1486
+ return {
1487
+ success: false,
1488
+ error: 'Cannot access Agent Workspace tables. Agent Workspace plugin may not be installed or activated.',
1489
+ suggestion: 'Install Agent Workspace plugin in ServiceNow: System Applications → All Available Applications → Agent Workspace'
1490
+ };
1001
1491
  }
1002
1492
  const workspaces = response.data.result;
1003
1493
  if (!workspaces.length) {
@@ -1037,10 +1527,21 @@ ${workspaceList.join('\n\n')}
1037
1527
  throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to discover workspaces: ${error}`);
1038
1528
  }
1039
1529
  }
1040
- // Mobile Implementation
1530
+ // Mobile Implementation
1041
1531
  async configureMobileApp(args) {
1042
1532
  try {
1043
- this.logger.info('Configuring mobile app...');
1533
+ this.logger.info('Configuring ServiceNow Mobile app...');
1534
+ // Validate mobile app tables access first
1535
+ const mobileTableCheck = await this.client.searchRecords('sys_push_notif_msg', '', 1);
1536
+ if (!mobileTableCheck.success) {
1537
+ return {
1538
+ success: false,
1539
+ error: 'ServiceNow Mobile app tables not accessible. This feature requires Mobile Publishing plugin and Mobile Application Management licensing.',
1540
+ suggestion: 'Install Mobile Publishing plugin: System Applications → ServiceNow Store → Search "Mobile Publishing". Requires separate licensing.',
1541
+ plugin_required: 'Mobile Publishing',
1542
+ licensing_note: 'Mobile Publishing is a paid plugin requiring additional ServiceNow licensing'
1543
+ };
1544
+ }
1044
1545
  const mobileConfig = {
1045
1546
  app_name: args.app_name,
1046
1547
  enabled_modules: args.enabled_modules ? args.enabled_modules.join(',') : '',
@@ -1052,6 +1553,21 @@ ${workspaceList.join('\n\n')}
1052
1553
  this.logger.trackAPICall('CREATE', 'sys_mobile_config', 1);
1053
1554
  const response = await this.client.createRecord('sys_mobile_config', mobileConfig);
1054
1555
  if (!response.success) {
1556
+ // Provide specific mobile error guidance
1557
+ if (response.error?.includes('400') || response.error?.includes('Bad Request')) {
1558
+ return {
1559
+ success: false,
1560
+ error: 'Mobile app configuration failed. ServiceNow Mobile Publishing plugin may not be installed or properly configured.',
1561
+ suggestion: 'Verify Mobile Publishing plugin is installed and activated. Check ServiceNow Store for Mobile Publishing application.'
1562
+ };
1563
+ }
1564
+ if (response.error?.includes('403') || response.error?.includes('Forbidden')) {
1565
+ return {
1566
+ success: false,
1567
+ error: 'Insufficient permissions for mobile app configuration. Requires mobile_admin role or admin privileges.',
1568
+ suggestion: 'Contact ServiceNow administrator for mobile application management permissions.'
1569
+ };
1570
+ }
1055
1571
  throw new Error(`Failed to configure mobile app: ${response.error}`);
1056
1572
  }
1057
1573
  return {
@@ -1078,6 +1594,16 @@ ${workspaceList.join('\n\n')}
1078
1594
  async createMobileLayout(args) {
1079
1595
  try {
1080
1596
  this.logger.info('Creating mobile layout...');
1597
+ // Validate mobile layout tables access
1598
+ const layoutTableCheck = await this.client.searchRecords('sys_mobile_layout', '', 1);
1599
+ if (!layoutTableCheck.success) {
1600
+ return {
1601
+ success: false,
1602
+ error: 'Mobile layout tables not accessible. Requires ServiceNow Mobile Publishing plugin and Mobile Device Management licensing.',
1603
+ suggestion: 'Install Mobile Publishing plugin from ServiceNow Store. Contact ServiceNow sales for Mobile Application Management licensing.',
1604
+ alternative: 'Use Service Portal widgets for mobile-responsive interfaces instead.'
1605
+ };
1606
+ }
1081
1607
  const layoutData = {
1082
1608
  name: args.name,
1083
1609
  table: args.table,
@@ -1153,6 +1679,16 @@ ${workspaceList.join('\n\n')}
1153
1679
  async configureOfflineSync(args) {
1154
1680
  try {
1155
1681
  this.logger.info('Configuring offline sync...');
1682
+ // Validate offline sync capabilities
1683
+ const syncTableCheck = await this.client.searchRecords('sys_offline_sync', '', 1);
1684
+ if (!syncTableCheck.success) {
1685
+ return {
1686
+ success: false,
1687
+ error: 'Offline sync not available. Requires ServiceNow Mobile Publishing plugin with offline capabilities.',
1688
+ suggestion: 'Install Mobile Publishing plugin for offline sync. Alternative: Use ServiceNow Agent mobile app for basic offline access.',
1689
+ licensing_note: 'Offline sync requires Mobile Publishing licensing (paid plugin)'
1690
+ };
1691
+ }
1156
1692
  const syncConfig = {
1157
1693
  table: args.table,
1158
1694
  filter: args.filter || '',
@@ -1308,6 +1844,982 @@ ${configList}${layoutsText}${offlineText}
1308
1844
  throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to discover mobile configs: ${error}`);
1309
1845
  }
1310
1846
  }
1847
+ // ==========================================
1848
+ // UI BUILDER IMPLEMENTATION METHODS
1849
+ // Official ServiceNow sys_ux_* API implementations
1850
+ // ==========================================
1851
+ /**
1852
+ * Create UI Builder Page using sys_ux_page table
1853
+ */
1854
+ async createUIBPage(args) {
1855
+ try {
1856
+ this.logger.info(`🏗️ Creating UI Builder page: ${args.name}`);
1857
+ // Create the page in sys_ux_page table
1858
+ const pageData = {
1859
+ name: args.name,
1860
+ title: args.title,
1861
+ description: args.description || '',
1862
+ application: args.application || 'global',
1863
+ theme: args.theme || 'standard',
1864
+ layout_type: args.layout_type || 'container',
1865
+ responsive: args.responsive !== false,
1866
+ public_read: args.public_read || false,
1867
+ active: args.active !== false
1868
+ };
1869
+ const pageResponse = await this.client.createRecord('sys_ux_page', pageData);
1870
+ if (!pageResponse.success) {
1871
+ throw new Error(`Failed to create UI Builder page: ${pageResponse.error}`);
1872
+ }
1873
+ const page = pageResponse.data;
1874
+ // Create page registry entry for routing
1875
+ const registryData = {
1876
+ page: page.sys_id,
1877
+ path: args.route,
1878
+ application: args.application || 'global',
1879
+ public_access: args.public_read || false,
1880
+ active: true
1881
+ };
1882
+ const registryResponse = await this.client.createRecord('sys_ux_page_registry', registryData);
1883
+ this.logger.info(`✅ UI Builder page created successfully: ${page.sys_id}`);
1884
+ return {
1885
+ success: true,
1886
+ page: page,
1887
+ route: registryResponse.success ? registryResponse.data : null,
1888
+ message: `UI Builder page '${args.name}' created with route '${args.route}'`
1889
+ };
1890
+ }
1891
+ catch (error) {
1892
+ this.logger.error('Failed to create UI Builder page:', error);
1893
+ throw error;
1894
+ }
1895
+ }
1896
+ /**
1897
+ * Update UI Builder Page
1898
+ */
1899
+ async updateUIBPage(args) {
1900
+ try {
1901
+ this.logger.info(`🔧 Updating UI Builder page: ${args.page_id}`);
1902
+ const updates = {};
1903
+ if (args.title)
1904
+ updates.title = args.title;
1905
+ if (args.description)
1906
+ updates.description = args.description;
1907
+ if (args.theme)
1908
+ updates.theme = args.theme;
1909
+ if (args.layout_type)
1910
+ updates.layout_type = args.layout_type;
1911
+ if (typeof args.responsive === 'boolean')
1912
+ updates.responsive = args.responsive;
1913
+ if (typeof args.active === 'boolean')
1914
+ updates.active = args.active;
1915
+ const response = await this.client.updateRecord('sys_ux_page', args.page_id, updates);
1916
+ if (!response.success) {
1917
+ throw new Error(`Failed to update UI Builder page: ${response.error}`);
1918
+ }
1919
+ this.logger.info('✅ UI Builder page updated successfully');
1920
+ return {
1921
+ success: true,
1922
+ page: response.data,
1923
+ message: `UI Builder page updated successfully`
1924
+ };
1925
+ }
1926
+ catch (error) {
1927
+ this.logger.error('Failed to update UI Builder page:', error);
1928
+ throw error;
1929
+ }
1930
+ }
1931
+ /**
1932
+ * Delete UI Builder Page with dependency validation
1933
+ */
1934
+ async deleteUIBPage(args) {
1935
+ try {
1936
+ this.logger.info(`🗑️ Deleting UI Builder page: ${args.page_id}`);
1937
+ // Check dependencies if validation enabled
1938
+ if (!args.force_delete) {
1939
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`, 1);
1940
+ if (elementsResponse.success && elementsResponse.data.result.length > 0) {
1941
+ return {
1942
+ success: false,
1943
+ error: 'Page has elements. Use force_delete: true to override or manually remove elements first.',
1944
+ dependencies: elementsResponse.data.result.length
1945
+ };
1946
+ }
1947
+ }
1948
+ // Clean up associated records first
1949
+ if (args.clean_orphaned_elements) {
1950
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`);
1951
+ if (elementsResponse.success) {
1952
+ for (const element of elementsResponse.data.result) {
1953
+ await this.client.deleteRecord('sys_ux_page_element', element.sys_id);
1954
+ }
1955
+ }
1956
+ }
1957
+ // Delete page registry entries
1958
+ const registryResponse = await this.client.searchRecords('sys_ux_page_registry', `page=${args.page_id}`);
1959
+ if (registryResponse.success) {
1960
+ for (const registry of registryResponse.data.result) {
1961
+ await this.client.deleteRecord('sys_ux_page_registry', registry.sys_id);
1962
+ }
1963
+ }
1964
+ // Delete the page
1965
+ const deleteResponse = await this.client.deleteRecord('sys_ux_page', args.page_id);
1966
+ if (!deleteResponse.success) {
1967
+ throw new Error(`Failed to delete UI Builder page: ${deleteResponse.error}`);
1968
+ }
1969
+ this.logger.info('✅ UI Builder page deleted successfully');
1970
+ return {
1971
+ success: true,
1972
+ message: 'UI Builder page and associated configurations deleted successfully'
1973
+ };
1974
+ }
1975
+ catch (error) {
1976
+ this.logger.error('Failed to delete UI Builder page:', error);
1977
+ throw error;
1978
+ }
1979
+ }
1980
+ /**
1981
+ * Discover UI Builder Pages
1982
+ */
1983
+ async discoverUIBPages(args) {
1984
+ try {
1985
+ this.logger.info('🔍 Discovering UI Builder pages...');
1986
+ const conditions = [];
1987
+ if (args.active_only)
1988
+ conditions.push('active=true');
1989
+ if (args.application)
1990
+ conditions.push(`application=${args.application}`);
1991
+ if (args.name_filter)
1992
+ conditions.push(`nameLIKE${args.name_filter}`);
1993
+ if (args.theme_filter)
1994
+ conditions.push(`theme=${args.theme_filter}`);
1995
+ const query = conditions.join('^');
1996
+ const pagesResponse = await this.client.searchRecords('sys_ux_page', query, args.limit || 50);
1997
+ if (!pagesResponse.success) {
1998
+ throw new Error(`Failed to discover UI Builder pages: ${pagesResponse.error}`);
1999
+ }
2000
+ const pages = pagesResponse.data.result;
2001
+ // Enrich with additional data if requested
2002
+ for (const page of pages) {
2003
+ if (args.include_routing) {
2004
+ const routeResponse = await this.client.searchRecords('sys_ux_page_registry', `page=${page.sys_id}`, 10);
2005
+ page.routes = routeResponse.success ? routeResponse.data.result : [];
2006
+ }
2007
+ if (args.include_elements) {
2008
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${page.sys_id}`, 100);
2009
+ page.elements = elementsResponse.success ? elementsResponse.data.result : [];
2010
+ }
2011
+ if (args.include_data_brokers) {
2012
+ const brokersResponse = await this.client.searchRecords('sys_ux_data_broker', `page=${page.sys_id}`, 50);
2013
+ page.data_brokers = brokersResponse.success ? brokersResponse.data.result : [];
2014
+ }
2015
+ }
2016
+ this.logger.info(`✅ Found ${pages.length} UI Builder pages`);
2017
+ return {
2018
+ success: true,
2019
+ pages: pages,
2020
+ count: pages.length
2021
+ };
2022
+ }
2023
+ catch (error) {
2024
+ this.logger.error('Failed to discover UI Builder pages:', error);
2025
+ throw error;
2026
+ }
2027
+ }
2028
+ /**
2029
+ * Create UI Builder Component using sys_ux_lib_component and sys_ux_lib_source_script
2030
+ */
2031
+ async createUIBComponent(args) {
2032
+ try {
2033
+ this.logger.info(`🧩 Creating UI Builder component: ${args.name}`);
2034
+ // First create the source script
2035
+ const sourceData = {
2036
+ name: args.name,
2037
+ source: args.source_script,
2038
+ version: args.version || '1.0.0',
2039
+ active: true
2040
+ };
2041
+ const sourceResponse = await this.client.createRecord('sys_ux_lib_source_script', sourceData);
2042
+ if (!sourceResponse.success) {
2043
+ throw new Error(`Failed to create component source: ${sourceResponse.error}`);
2044
+ }
2045
+ // Then create the component definition
2046
+ const componentData = {
2047
+ name: args.name,
2048
+ label: args.label,
2049
+ description: args.description || '',
2050
+ category: args.category || 'custom',
2051
+ source_script: sourceResponse.data.sys_id,
2052
+ properties_schema: args.properties_schema ? JSON.stringify(args.properties_schema) : '{}',
2053
+ events: args.events ? args.events.join(',') : '',
2054
+ dependencies: args.dependencies ? args.dependencies.join(',') : '',
2055
+ styling: args.styling ? JSON.stringify(args.styling) : '{}',
2056
+ version: args.version || '1.0.0',
2057
+ tags: args.tags ? args.tags.join(',') : '',
2058
+ active: true
2059
+ };
2060
+ const componentResponse = await this.client.createRecord('sys_ux_lib_component', componentData);
2061
+ if (!componentResponse.success) {
2062
+ // Cleanup source script on failure
2063
+ await this.client.deleteRecord('sys_ux_lib_source_script', sourceResponse.data.sys_id);
2064
+ throw new Error(`Failed to create component: ${componentResponse.error}`);
2065
+ }
2066
+ this.logger.info('✅ UI Builder component created successfully');
2067
+ return {
2068
+ success: true,
2069
+ component: componentResponse.data,
2070
+ source_script: sourceResponse.data,
2071
+ message: `Custom UI Builder component '${args.name}' created successfully`
2072
+ };
2073
+ }
2074
+ catch (error) {
2075
+ this.logger.error('Failed to create UI Builder component:', error);
2076
+ throw error;
2077
+ }
2078
+ }
2079
+ /**
2080
+ * Update UI Builder Component
2081
+ */
2082
+ async updateUIBComponent(args) {
2083
+ try {
2084
+ this.logger.info(`🔧 Updating UI Builder component: ${args.component_id}`);
2085
+ const updates = {};
2086
+ if (args.label)
2087
+ updates.label = args.label;
2088
+ if (args.description)
2089
+ updates.description = args.description;
2090
+ if (args.properties_schema)
2091
+ updates.properties_schema = JSON.stringify(args.properties_schema);
2092
+ if (args.styling)
2093
+ updates.styling = JSON.stringify(args.styling);
2094
+ if (args.version)
2095
+ updates.version = args.version;
2096
+ if (args.events)
2097
+ updates.events = args.events.join(',');
2098
+ if (args.dependencies)
2099
+ updates.dependencies = args.dependencies.join(',');
2100
+ if (typeof args.active === 'boolean')
2101
+ updates.active = args.active;
2102
+ const componentResponse = await this.client.updateRecord('sys_ux_lib_component', args.component_id, updates);
2103
+ if (!componentResponse.success) {
2104
+ throw new Error(`Failed to update component: ${componentResponse.error}`);
2105
+ }
2106
+ // Update source script if provided
2107
+ if (args.source_script) {
2108
+ const component = componentResponse.data;
2109
+ if (component.source_script) {
2110
+ await this.client.updateRecord('sys_ux_lib_source_script', component.source_script, {
2111
+ source: args.source_script,
2112
+ version: args.version || component.version
2113
+ });
2114
+ }
2115
+ }
2116
+ this.logger.info('✅ UI Builder component updated successfully');
2117
+ return {
2118
+ success: true,
2119
+ component: componentResponse.data,
2120
+ message: 'UI Builder component updated successfully'
2121
+ };
2122
+ }
2123
+ catch (error) {
2124
+ this.logger.error('Failed to update UI Builder component:', error);
2125
+ throw error;
2126
+ }
2127
+ }
2128
+ /**
2129
+ * Discover UI Builder Components
2130
+ */
2131
+ async discoverUIBComponents(args) {
2132
+ try {
2133
+ this.logger.info('🔍 Discovering UI Builder components...');
2134
+ const conditions = [];
2135
+ if (args.category)
2136
+ conditions.push(`category=${args.category}`);
2137
+ if (args.custom_only)
2138
+ conditions.push('category=custom');
2139
+ if (args.built_in_only)
2140
+ conditions.push('category!=custom');
2141
+ if (args.name_filter)
2142
+ conditions.push(`nameLIKE${args.name_filter}^ORlabelLIKE${args.name_filter}`);
2143
+ if (args.version_filter)
2144
+ conditions.push(`versionLIKE${args.version_filter}`);
2145
+ if (args.application)
2146
+ conditions.push(`application=${args.application}`);
2147
+ const query = conditions.join('^');
2148
+ const componentsResponse = await this.client.searchRecords('sys_ux_lib_component', query, args.limit || 100);
2149
+ if (!componentsResponse.success) {
2150
+ throw new Error(`Failed to discover components: ${componentsResponse.error}`);
2151
+ }
2152
+ const components = componentsResponse.data.result;
2153
+ // Enrich with additional data if requested
2154
+ for (const component of components) {
2155
+ if (args.include_source && component.source_script) {
2156
+ const sourceResponse = await this.client.getRecord('sys_ux_lib_source_script', component.source_script);
2157
+ component.source_code = sourceResponse.success ? sourceResponse.data : null;
2158
+ }
2159
+ if (args.include_usage_stats) {
2160
+ const usageResponse = await this.client.searchRecords('sys_ux_page_element', `component=${component.sys_id}^ORcomponent=${component.name}`);
2161
+ component.usage_count = usageResponse.success ? usageResponse.data.result.length : 0;
2162
+ }
2163
+ if (args.include_dependencies && component.dependencies) {
2164
+ component.dependency_list = component.dependencies.split(',').map(d => d.trim()).filter(d => d);
2165
+ }
2166
+ }
2167
+ this.logger.info(`✅ Found ${components.length} UI Builder components`);
2168
+ return {
2169
+ success: true,
2170
+ components: components,
2171
+ count: components.length
2172
+ };
2173
+ }
2174
+ catch (error) {
2175
+ this.logger.error('Failed to discover UI Builder components:', error);
2176
+ throw error;
2177
+ }
2178
+ }
2179
+ /**
2180
+ * Clone UI Builder Component
2181
+ */
2182
+ async cloneUIBComponent(args) {
2183
+ try {
2184
+ this.logger.info(`📋 Cloning UI Builder component: ${args.source_component_id} → ${args.new_name}`);
2185
+ // Get source component
2186
+ const sourceResponse = await this.client.getRecord('sys_ux_lib_component', args.source_component_id);
2187
+ if (!sourceResponse.success) {
2188
+ throw new Error(`Source component not found: ${args.source_component_id}`);
2189
+ }
2190
+ const sourceComponent = sourceResponse.data;
2191
+ // Get source script
2192
+ let sourceCode = '';
2193
+ if (sourceComponent.source_script) {
2194
+ const sourceScriptResponse = await this.client.getRecord('sys_ux_lib_source_script', sourceComponent.source_script);
2195
+ if (sourceScriptResponse.success) {
2196
+ sourceCode = sourceScriptResponse.data.source || '';
2197
+ }
2198
+ }
2199
+ // Apply modifications to source code if provided
2200
+ if (args.modifications) {
2201
+ for (const [find, replace] of Object.entries(args.modifications)) {
2202
+ sourceCode = sourceCode.replace(new RegExp(find, 'g'), replace);
2203
+ }
2204
+ }
2205
+ // Create cloned component
2206
+ const cloneData = {
2207
+ name: args.new_name,
2208
+ label: args.new_label,
2209
+ description: args.description || `Clone of ${sourceComponent.label}`,
2210
+ category: args.category || 'custom',
2211
+ source_script: sourceCode,
2212
+ properties_schema: sourceComponent.properties_schema,
2213
+ events: sourceComponent.events,
2214
+ dependencies: sourceComponent.dependencies,
2215
+ styling: sourceComponent.styling,
2216
+ version: args.version || '1.0.0'
2217
+ };
2218
+ const cloneResult = await this.createUIBComponent(cloneData);
2219
+ this.logger.info('✅ UI Builder component cloned successfully');
2220
+ return {
2221
+ success: true,
2222
+ cloned_component: cloneResult.component,
2223
+ source_component: sourceComponent,
2224
+ message: `Component '${args.new_name}' cloned from '${sourceComponent.label}'`
2225
+ };
2226
+ }
2227
+ catch (error) {
2228
+ this.logger.error('Failed to clone UI Builder component:', error);
2229
+ throw error;
2230
+ }
2231
+ }
2232
+ /**
2233
+ * Create UI Builder Data Broker
2234
+ */
2235
+ async createUIBDataBroker(args) {
2236
+ try {
2237
+ this.logger.info(`🔗 Creating UI Builder data broker: ${args.name}`);
2238
+ const brokerData = {
2239
+ name: args.name,
2240
+ label: args.label,
2241
+ type: args.type || 'table',
2242
+ table: args.table || '',
2243
+ query: args.query || '',
2244
+ script: args.script || '',
2245
+ rest_message: args.rest_message || '',
2246
+ fields: args.fields ? args.fields.join(',') : '',
2247
+ auto_refresh: args.auto_refresh || false,
2248
+ refresh_interval: args.refresh_interval || 30,
2249
+ cache_duration: args.cache_duration || 300,
2250
+ max_records: args.max_records || 1000,
2251
+ active: true
2252
+ };
2253
+ const response = await this.client.createRecord('sys_ux_data_broker', brokerData);
2254
+ if (!response.success) {
2255
+ throw new Error(`Failed to create data broker: ${response.error}`);
2256
+ }
2257
+ this.logger.info('✅ UI Builder data broker created successfully');
2258
+ return {
2259
+ success: true,
2260
+ data_broker: response.data,
2261
+ message: `Data broker '${args.name}' created for ${args.type} type`
2262
+ };
2263
+ }
2264
+ catch (error) {
2265
+ this.logger.error('Failed to create UI Builder data broker:', error);
2266
+ throw error;
2267
+ }
2268
+ }
2269
+ /**
2270
+ * Configure UI Builder Data Broker
2271
+ */
2272
+ async configureUIBDataBroker(args) {
2273
+ try {
2274
+ this.logger.info(`⚙️ Configuring UI Builder data broker: ${args.broker_id}`);
2275
+ const updates = {};
2276
+ if (args.query)
2277
+ updates.query = args.query;
2278
+ if (args.fields)
2279
+ updates.fields = args.fields.join(',');
2280
+ if (typeof args.auto_refresh === 'boolean')
2281
+ updates.auto_refresh = args.auto_refresh;
2282
+ if (args.refresh_interval)
2283
+ updates.refresh_interval = args.refresh_interval;
2284
+ if (args.cache_duration)
2285
+ updates.cache_duration = args.cache_duration;
2286
+ if (args.max_records)
2287
+ updates.max_records = args.max_records;
2288
+ if (typeof args.active === 'boolean')
2289
+ updates.active = args.active;
2290
+ const response = await this.client.updateRecord('sys_ux_data_broker', args.broker_id, updates);
2291
+ if (!response.success) {
2292
+ throw new Error(`Failed to configure data broker: ${response.error}`);
2293
+ }
2294
+ this.logger.info('✅ UI Builder data broker configured successfully');
2295
+ return {
2296
+ success: true,
2297
+ data_broker: response.data,
2298
+ message: 'Data broker configuration updated successfully'
2299
+ };
2300
+ }
2301
+ catch (error) {
2302
+ this.logger.error('Failed to configure UI Builder data broker:', error);
2303
+ throw error;
2304
+ }
2305
+ }
2306
+ /**
2307
+ * Add UI Builder Page Element
2308
+ */
2309
+ async addUIBPageElement(args) {
2310
+ try {
2311
+ this.logger.info(`➕ Adding element to UI Builder page: ${args.component}`);
2312
+ const elementData = {
2313
+ page: args.page_id,
2314
+ component: args.component,
2315
+ container_id: args.container_id || '',
2316
+ position: args.position || 0,
2317
+ properties: args.properties ? JSON.stringify(args.properties) : '{}',
2318
+ data_broker: args.data_broker || '',
2319
+ responsive_config: args.responsive_config ? JSON.stringify(args.responsive_config) : '{}',
2320
+ conditional_display: args.conditional_display || '',
2321
+ css_classes: args.css_classes ? args.css_classes.join(' ') : '',
2322
+ inline_styles: args.inline_styles ? JSON.stringify(args.inline_styles) : '{}',
2323
+ active: true
2324
+ };
2325
+ const response = await this.client.createRecord('sys_ux_page_element', elementData);
2326
+ if (!response.success) {
2327
+ throw new Error(`Failed to add page element: ${response.error}`);
2328
+ }
2329
+ this.logger.info('✅ UI Builder page element added successfully');
2330
+ return {
2331
+ success: true,
2332
+ element: response.data,
2333
+ message: `Component '${args.component}' added to page successfully`
2334
+ };
2335
+ }
2336
+ catch (error) {
2337
+ this.logger.error('Failed to add UI Builder page element:', error);
2338
+ throw error;
2339
+ }
2340
+ }
2341
+ /**
2342
+ * Update UI Builder Page Element
2343
+ */
2344
+ async updateUIBPageElement(args) {
2345
+ try {
2346
+ this.logger.info(`🔧 Updating UI Builder page element: ${args.element_id}`);
2347
+ const updates = {};
2348
+ if (args.properties)
2349
+ updates.properties = JSON.stringify(args.properties);
2350
+ if (args.position !== undefined)
2351
+ updates.position = args.position;
2352
+ if (args.data_broker)
2353
+ updates.data_broker = args.data_broker;
2354
+ if (args.responsive_config)
2355
+ updates.responsive_config = JSON.stringify(args.responsive_config);
2356
+ if (args.conditional_display)
2357
+ updates.conditional_display = args.conditional_display;
2358
+ if (args.css_classes)
2359
+ updates.css_classes = args.css_classes.join(' ');
2360
+ if (args.inline_styles)
2361
+ updates.inline_styles = JSON.stringify(args.inline_styles);
2362
+ const response = await this.client.updateRecord('sys_ux_page_element', args.element_id, updates);
2363
+ if (!response.success) {
2364
+ throw new Error(`Failed to update page element: ${response.error}`);
2365
+ }
2366
+ this.logger.info('✅ UI Builder page element updated successfully');
2367
+ return {
2368
+ success: true,
2369
+ element: response.data,
2370
+ message: 'Page element updated successfully'
2371
+ };
2372
+ }
2373
+ catch (error) {
2374
+ this.logger.error('Failed to update UI Builder page element:', error);
2375
+ throw error;
2376
+ }
2377
+ }
2378
+ /**
2379
+ * Remove UI Builder Page Element
2380
+ */
2381
+ async removeUIBPageElement(args) {
2382
+ try {
2383
+ this.logger.info(`🗑️ Removing UI Builder page element: ${args.element_id}`);
2384
+ // Validate dependencies if requested
2385
+ if (args.validate_dependencies) {
2386
+ const dependentResponse = await this.client.searchRecords('sys_ux_page_element', `container_id=${args.element_id}`, 10);
2387
+ if (dependentResponse.success && dependentResponse.data.result.length > 0) {
2388
+ return {
2389
+ success: false,
2390
+ error: 'Element has dependent child elements. Remove children first or use validate_dependencies: false',
2391
+ dependent_elements: dependentResponse.data.result.length
2392
+ };
2393
+ }
2394
+ }
2395
+ const response = await this.client.deleteRecord('sys_ux_page_element', args.element_id);
2396
+ if (!response.success) {
2397
+ throw new Error(`Failed to remove page element: ${response.error}`);
2398
+ }
2399
+ this.logger.info('✅ UI Builder page element removed successfully');
2400
+ return {
2401
+ success: true,
2402
+ message: 'Page element removed successfully'
2403
+ };
2404
+ }
2405
+ catch (error) {
2406
+ this.logger.error('Failed to remove UI Builder page element:', error);
2407
+ throw error;
2408
+ }
2409
+ }
2410
+ /**
2411
+ * Create UI Builder Page Registry (Routing)
2412
+ */
2413
+ async createUIBPageRegistry(args) {
2414
+ try {
2415
+ this.logger.info(`🛣️ Creating UI Builder page registry: ${args.path}`);
2416
+ const registryData = {
2417
+ page: args.page_id,
2418
+ path: args.path,
2419
+ application: args.application || 'global',
2420
+ roles: args.roles ? args.roles.join(',') : '',
2421
+ public_access: args.public_access || false,
2422
+ redirect_url: args.redirect_url || '',
2423
+ meta_title: args.meta_title || '',
2424
+ meta_description: args.meta_description || '',
2425
+ parameter_mapping: args.parameter_mapping ? JSON.stringify(args.parameter_mapping) : '{}',
2426
+ cache_control: args.cache_control || '',
2427
+ active: true
2428
+ };
2429
+ const response = await this.client.createRecord('sys_ux_page_registry', registryData);
2430
+ if (!response.success) {
2431
+ throw new Error(`Failed to create page registry: ${response.error}`);
2432
+ }
2433
+ this.logger.info('✅ UI Builder page registry created successfully');
2434
+ return {
2435
+ success: true,
2436
+ registry: response.data,
2437
+ message: `Page routing configured for path '${args.path}'`
2438
+ };
2439
+ }
2440
+ catch (error) {
2441
+ this.logger.error('Failed to create UI Builder page registry:', error);
2442
+ throw error;
2443
+ }
2444
+ }
2445
+ /**
2446
+ * Discover UI Builder Routes
2447
+ */
2448
+ async discoverUIBRoutes(args) {
2449
+ try {
2450
+ this.logger.info('🔍 Discovering UI Builder routes...');
2451
+ const conditions = [];
2452
+ if (args.application)
2453
+ conditions.push(`application=${args.application}`);
2454
+ if (args.active_only)
2455
+ conditions.push('active=true');
2456
+ if (args.path_pattern)
2457
+ conditions.push(`pathLIKE${args.path_pattern}`);
2458
+ if (args.role_filter)
2459
+ conditions.push(`rolesLIKE${args.role_filter}`);
2460
+ const query = conditions.join('^');
2461
+ const routesResponse = await this.client.searchRecords('sys_ux_page_registry', query, 100);
2462
+ if (!routesResponse.success) {
2463
+ throw new Error(`Failed to discover routes: ${routesResponse.error}`);
2464
+ }
2465
+ const routes = routesResponse.data.result;
2466
+ // Enrich with additional data if requested
2467
+ for (const route of routes) {
2468
+ if (args.include_security && route.roles) {
2469
+ route.required_roles = route.roles.split(',').map(r => r.trim()).filter(r => r);
2470
+ }
2471
+ if (args.include_parameters && route.parameter_mapping) {
2472
+ try {
2473
+ route.parameters = JSON.parse(route.parameter_mapping);
2474
+ }
2475
+ catch (e) {
2476
+ route.parameters = {};
2477
+ }
2478
+ }
2479
+ // Add page information
2480
+ if (route.page) {
2481
+ const pageResponse = await this.client.getRecord('sys_ux_page', route.page);
2482
+ route.page_info = pageResponse.success ? pageResponse.data : null;
2483
+ }
2484
+ }
2485
+ this.logger.info(`✅ Found ${routes.length} UI Builder routes`);
2486
+ return {
2487
+ success: true,
2488
+ routes: routes,
2489
+ count: routes.length
2490
+ };
2491
+ }
2492
+ catch (error) {
2493
+ this.logger.error('Failed to discover UI Builder routes:', error);
2494
+ throw error;
2495
+ }
2496
+ }
2497
+ /**
2498
+ * Create UI Builder Client Script
2499
+ */
2500
+ async createUIBClientScript(args) {
2501
+ try {
2502
+ this.logger.info(`📝 Creating UI Builder client script: ${args.name}`);
2503
+ const scriptData = {
2504
+ page: args.page_id,
2505
+ name: args.name,
2506
+ type: args.type,
2507
+ script: args.script,
2508
+ component_reference: args.component_reference || '',
2509
+ event_name: args.event_name || '',
2510
+ execution_order: args.execution_order || 100,
2511
+ async_execution: args.async_execution || false,
2512
+ error_handling: args.error_handling || 'log',
2513
+ active: args.active !== false
2514
+ };
2515
+ const response = await this.client.createRecord('sys_ux_client_script', scriptData);
2516
+ if (!response.success) {
2517
+ throw new Error(`Failed to create client script: ${response.error}`);
2518
+ }
2519
+ this.logger.info('✅ UI Builder client script created successfully');
2520
+ return {
2521
+ success: true,
2522
+ script: response.data,
2523
+ message: `Client script '${args.name}' created for ${args.type} trigger`
2524
+ };
2525
+ }
2526
+ catch (error) {
2527
+ this.logger.error('Failed to create UI Builder client script:', error);
2528
+ throw error;
2529
+ }
2530
+ }
2531
+ /**
2532
+ * Create UI Builder Client State
2533
+ */
2534
+ async createUIBClientState(args) {
2535
+ try {
2536
+ this.logger.info(`💾 Creating UI Builder client state: ${args.state_name}`);
2537
+ const stateData = {
2538
+ page: args.page_id,
2539
+ state_name: args.state_name,
2540
+ initial_value: args.initial_value,
2541
+ scope: args.scope || 'page',
2542
+ persistent: args.persistent || false,
2543
+ reactive: args.reactive !== false,
2544
+ validation_schema: args.validation_schema ? JSON.stringify(args.validation_schema) : '{}',
2545
+ description: args.description || '',
2546
+ active: true
2547
+ };
2548
+ const response = await this.client.createRecord('sys_ux_client_state', stateData);
2549
+ if (!response.success) {
2550
+ throw new Error(`Failed to create client state: ${response.error}`);
2551
+ }
2552
+ this.logger.info('✅ UI Builder client state created successfully');
2553
+ return {
2554
+ success: true,
2555
+ state: response.data,
2556
+ message: `Client state '${args.state_name}' configured with ${args.scope} scope`
2557
+ };
2558
+ }
2559
+ catch (error) {
2560
+ this.logger.error('Failed to create UI Builder client state:', error);
2561
+ throw error;
2562
+ }
2563
+ }
2564
+ /**
2565
+ * Create UI Builder Event
2566
+ */
2567
+ async createUIBEvent(args) {
2568
+ try {
2569
+ this.logger.info(`⚡ Creating UI Builder event: ${args.name}`);
2570
+ const eventData = {
2571
+ name: args.name,
2572
+ label: args.label,
2573
+ description: args.description || '',
2574
+ payload_schema: args.payload_schema ? JSON.stringify(args.payload_schema) : '{}',
2575
+ component_scope: args.component_scope || '',
2576
+ global_event: args.global_event || false,
2577
+ bubbles: args.bubbles !== false,
2578
+ cancelable: args.cancelable !== false,
2579
+ active: true
2580
+ };
2581
+ const response = await this.client.createRecord('sys_ux_event', eventData);
2582
+ if (!response.success) {
2583
+ throw new Error(`Failed to create event: ${response.error}`);
2584
+ }
2585
+ this.logger.info('✅ UI Builder event created successfully');
2586
+ return {
2587
+ success: true,
2588
+ event: response.data,
2589
+ message: `Custom event '${args.name}' created ${args.global_event ? '(global)' : '(scoped)'}`
2590
+ };
2591
+ }
2592
+ catch (error) {
2593
+ this.logger.error('Failed to create UI Builder event:', error);
2594
+ throw error;
2595
+ }
2596
+ }
2597
+ /**
2598
+ * Analyze UI Builder Page Performance
2599
+ */
2600
+ async analyzeUIBPagePerformance(args) {
2601
+ try {
2602
+ this.logger.info(`📊 Analyzing UI Builder page performance: ${args.page_id}`);
2603
+ const analysis = {
2604
+ page_id: args.page_id,
2605
+ analysis_date: new Date().toISOString(),
2606
+ components: [],
2607
+ data_brokers: [],
2608
+ client_scripts: [],
2609
+ recommendations: [],
2610
+ total_components: 0,
2611
+ page_info: null
2612
+ };
2613
+ // Get page info
2614
+ const pageResponse = await this.client.getRecord('sys_ux_page', args.page_id);
2615
+ if (!pageResponse.success) {
2616
+ throw new Error('Page not found');
2617
+ }
2618
+ analysis.page_info = pageResponse.data;
2619
+ // Analyze components if requested
2620
+ if (args.include_components) {
2621
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`, 100);
2622
+ if (elementsResponse.success) {
2623
+ analysis.total_components = elementsResponse.data.result.length;
2624
+ analysis.components = elementsResponse.data.result.map(element => ({
2625
+ component: element.component,
2626
+ position: element.position,
2627
+ has_data_broker: !!element.data_broker,
2628
+ has_conditional_display: !!element.conditional_display
2629
+ }));
2630
+ }
2631
+ }
2632
+ // Analyze data brokers if requested
2633
+ if (args.include_data_broker_stats) {
2634
+ const brokersResponse = await this.client.searchRecords('sys_ux_data_broker', `page=${args.page_id}`, 50);
2635
+ if (brokersResponse.success) {
2636
+ analysis.data_brokers = brokersResponse.data.result.map(broker => ({
2637
+ name: broker.name,
2638
+ type: broker.type,
2639
+ table: broker.table,
2640
+ auto_refresh: broker.auto_refresh,
2641
+ cache_duration: broker.cache_duration
2642
+ }));
2643
+ }
2644
+ }
2645
+ // Analyze client scripts if requested
2646
+ if (args.include_client_scripts) {
2647
+ const scriptsResponse = await this.client.searchRecords('sys_ux_client_script', `page=${args.page_id}`, 50);
2648
+ if (scriptsResponse.success) {
2649
+ analysis.client_scripts = scriptsResponse.data.result.map(script => ({
2650
+ name: script.name,
2651
+ type: script.type,
2652
+ execution_order: script.execution_order,
2653
+ async_execution: script.async_execution
2654
+ }));
2655
+ }
2656
+ }
2657
+ // Generate performance recommendations
2658
+ if (analysis.total_components > 20) {
2659
+ analysis.recommendations.push('Consider breaking page into smaller pages - many components may impact performance');
2660
+ }
2661
+ if (analysis.data_brokers.some(db => db.auto_refresh && db.cache_duration < 60)) {
2662
+ analysis.recommendations.push('Some data brokers have short cache duration with auto-refresh - consider optimizing');
2663
+ }
2664
+ if (analysis.client_scripts.length > 10) {
2665
+ analysis.recommendations.push('Many client scripts detected - consider consolidating for better performance');
2666
+ }
2667
+ this.logger.info('✅ UI Builder page performance analysis completed');
2668
+ return {
2669
+ success: true,
2670
+ analysis: analysis,
2671
+ summary: `Page has ${analysis.total_components || 0} components, ${analysis.data_brokers.length} data brokers, ${analysis.client_scripts.length} scripts`
2672
+ };
2673
+ }
2674
+ catch (error) {
2675
+ this.logger.error('Failed to analyze UI Builder page performance:', error);
2676
+ throw error;
2677
+ }
2678
+ }
2679
+ /**
2680
+ * Validate UI Builder Page Structure
2681
+ */
2682
+ async validateUIBPageStructure(args) {
2683
+ try {
2684
+ this.logger.info(`✅ Validating UI Builder page structure: ${args.page_id}`);
2685
+ const validation = {
2686
+ page_id: args.page_id,
2687
+ validation_date: new Date().toISOString(),
2688
+ is_valid: true,
2689
+ errors: [],
2690
+ warnings: [],
2691
+ info: []
2692
+ };
2693
+ // Get page info
2694
+ const pageResponse = await this.client.getRecord('sys_ux_page', args.page_id);
2695
+ if (!pageResponse.success) {
2696
+ validation.errors.push('Page not found');
2697
+ validation.is_valid = false;
2698
+ return { success: true, validation };
2699
+ }
2700
+ const page = pageResponse.data;
2701
+ // Check routing if requested
2702
+ if (args.check_routing) {
2703
+ const routeResponse = await this.client.searchRecords('sys_ux_page_registry', `page=${args.page_id}`, 1);
2704
+ if (!routeResponse.success || routeResponse.data.result.length === 0) {
2705
+ validation.warnings.push('Page has no routing configuration - may not be accessible');
2706
+ }
2707
+ }
2708
+ // Check data brokers if requested
2709
+ if (args.check_data_brokers) {
2710
+ const brokersResponse = await this.client.searchRecords('sys_ux_data_broker', `page=${args.page_id}`);
2711
+ if (brokersResponse.success) {
2712
+ for (const broker of brokersResponse.data.result) {
2713
+ if (broker.type === 'table' && !broker.table) {
2714
+ validation.errors.push(`Data broker '${broker.name}' has no table configured`);
2715
+ validation.is_valid = false;
2716
+ }
2717
+ if (broker.type === 'script' && !broker.script) {
2718
+ validation.errors.push(`Data broker '${broker.name}' has no script configured`);
2719
+ validation.is_valid = false;
2720
+ }
2721
+ }
2722
+ }
2723
+ }
2724
+ // Check component dependencies if requested
2725
+ if (args.check_component_dependencies) {
2726
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`);
2727
+ if (elementsResponse.success) {
2728
+ for (const element of elementsResponse.data.result) {
2729
+ const componentResponse = await this.client.searchRecords('sys_ux_lib_component', `name=${element.component}^ORsys_id=${element.component}`, 1);
2730
+ if (!componentResponse.success || componentResponse.data.result.length === 0) {
2731
+ validation.errors.push(`Page element references unknown component: ${element.component}`);
2732
+ validation.is_valid = false;
2733
+ }
2734
+ }
2735
+ }
2736
+ }
2737
+ // Check security if requested
2738
+ if (args.check_security) {
2739
+ const routeResponse = await this.client.searchRecords('sys_ux_page_registry', `page=${args.page_id}`, 1);
2740
+ if (routeResponse.success && routeResponse.data.result.length > 0) {
2741
+ const route = routeResponse.data.result[0];
2742
+ if (!route.public_access && (!route.roles || route.roles.trim() === '')) {
2743
+ validation.warnings.push('Page is not public but has no role restrictions - check access control');
2744
+ }
2745
+ }
2746
+ }
2747
+ // Performance checks if requested
2748
+ if (args.check_performance) {
2749
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`);
2750
+ if (elementsResponse.success && elementsResponse.data.result.length > 15) {
2751
+ validation.warnings.push('Page has many components (>15) - consider performance optimization');
2752
+ }
2753
+ }
2754
+ // Accessibility checks if requested
2755
+ if (args.check_accessibility) {
2756
+ validation.info.push('Accessibility validation requires manual review - check for proper ARIA labels and keyboard navigation');
2757
+ }
2758
+ validation.info.push(`Page '${page.name}' validation completed`);
2759
+ validation.info.push(`Found ${validation.errors.length} errors and ${validation.warnings.length} warnings`);
2760
+ this.logger.info('✅ UI Builder page structure validation completed');
2761
+ return {
2762
+ success: true,
2763
+ validation: validation,
2764
+ summary: `Validation ${validation.is_valid ? 'PASSED' : 'FAILED'}: ${validation.errors.length} errors, ${validation.warnings.length} warnings`
2765
+ };
2766
+ }
2767
+ catch (error) {
2768
+ this.logger.error('Failed to validate UI Builder page structure:', error);
2769
+ throw error;
2770
+ }
2771
+ }
2772
+ /**
2773
+ * Discover UI Builder Page Usage
2774
+ */
2775
+ async discoverUIBPageUsage(args) {
2776
+ try {
2777
+ this.logger.info(`📈 Analyzing UI Builder page usage: ${args.page_id}`);
2778
+ // Structural usage analysis
2779
+ const usage = {
2780
+ page_id: args.page_id,
2781
+ analysis_date: new Date().toISOString(),
2782
+ components_count: 0,
2783
+ data_brokers_count: 0,
2784
+ client_scripts_count: 0,
2785
+ routes_count: 0,
2786
+ complexity_score: 0
2787
+ };
2788
+ // Count components
2789
+ const elementsResponse = await this.client.searchRecords('sys_ux_page_element', `page=${args.page_id}`);
2790
+ if (elementsResponse.success) {
2791
+ usage.components_count = elementsResponse.data.result.length;
2792
+ }
2793
+ // Count data brokers
2794
+ const brokersResponse = await this.client.searchRecords('sys_ux_data_broker', `page=${args.page_id}`);
2795
+ if (brokersResponse.success) {
2796
+ usage.data_brokers_count = brokersResponse.data.result.length;
2797
+ }
2798
+ // Count client scripts
2799
+ const scriptsResponse = await this.client.searchRecords('sys_ux_client_script', `page=${args.page_id}`);
2800
+ if (scriptsResponse.success) {
2801
+ usage.client_scripts_count = scriptsResponse.data.result.length;
2802
+ }
2803
+ // Count routes
2804
+ const routesResponse = await this.client.searchRecords('sys_ux_page_registry', `page=${args.page_id}`);
2805
+ if (routesResponse.success) {
2806
+ usage.routes_count = routesResponse.data.result.length;
2807
+ }
2808
+ // Calculate complexity score
2809
+ usage.complexity_score = (usage.components_count * 2) + (usage.data_brokers_count * 3) + (usage.client_scripts_count * 4);
2810
+ this.logger.info('✅ UI Builder page usage analysis completed');
2811
+ return {
2812
+ success: true,
2813
+ usage: usage,
2814
+ complexity: usage.complexity_score < 20 ? 'Simple' : usage.complexity_score < 50 ? 'Moderate' : 'Complex',
2815
+ summary: `${usage.components_count} components, ${usage.data_brokers_count} data brokers, ${usage.client_scripts_count} scripts`
2816
+ };
2817
+ }
2818
+ catch (error) {
2819
+ this.logger.error('Failed to analyze UI Builder page usage:', error);
2820
+ throw error;
2821
+ }
2822
+ }
1311
2823
  async run() {
1312
2824
  const transport = new stdio_js_1.StdioServerTransport();
1313
2825
  await this.server.connect(transport);