snow-flow 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/{.claude/mcp-config.json → .mcp.json} +13 -12
  2. package/.releaserc.json +47 -0
  3. package/README.md +6 -0
  4. package/package.json +1 -1
  5. package/.claude/claude-settings.json +0 -15
  6. package/.claude/commands/analysis/README.md +0 -9
  7. package/.claude/commands/automation/README.md +0 -9
  8. package/.claude/commands/github/README.md +0 -11
  9. package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
  10. package/.claude/commands/hooks/README.md +0 -11
  11. package/.claude/commands/monitoring/README.md +0 -9
  12. package/.claude/commands/optimization/README.md +0 -9
  13. package/.claude/commands/training/README.md +0 -9
  14. package/.claude/commands/workflows/README.md +0 -9
  15. package/.claude/config.json +0 -36
  16. package/.claude/helpers/github-setup.sh +0 -28
  17. package/.claude/helpers/quick-start.sh +0 -19
  18. package/.claude/helpers/setup-mcp.sh +0 -18
  19. package/.claude/settings.json +0 -114
  20. package/.claude/settings.local.json +0 -33
  21. package/.claude-flow/metrics/agent-metrics.json +0 -1
  22. package/.claude-flow/metrics/performance.json +0 -9
  23. package/.claude-flow/metrics/system-metrics.json +0 -15986
  24. package/.claude-flow/metrics/task-metrics.json +0 -10
  25. package/.roo/README.md +0 -402
  26. package/.roo/mcp-list.txt +0 -257
  27. package/.roo/mcp.json +0 -32
  28. package/.roo/workflows/basic-tdd.json +0 -32
  29. package/.roomodes +0 -201
  30. package/CLAUDE.md +0 -393
  31. package/bin/snow-flow.js +0 -3
  32. package/dist/cli.js.bak +0 -2052
  33. package/dist/config/snow-flow-config.d.ts +0 -1492
  34. package/dist/config/snow-flow-config.js +0 -938
  35. package/scripts/create-env.js +0 -91
  36. package/scripts/postinstall.js +0 -30
  37. package/scripts/register-mcp-servers.js +0 -210
  38. package/scripts/reset-mcp-servers.js +0 -246
  39. package/scripts/setup-mcp.js +0 -106
  40. package/scripts/update-version.js +0 -31
  41. package/src/agents/README.md +0 -192
  42. package/src/agents/base-agent.ts +0 -251
  43. package/src/agents/coordinator.ts +0 -971
  44. package/src/agents/index.ts +0 -18
  45. package/src/agents/queen-403-handler.ts +0 -230
  46. package/src/agents/queen-agent.ts +0 -1399
  47. package/src/agents/script-writer-agent.ts +0 -769
  48. package/src/agents/security-agent.ts +0 -726
  49. package/src/agents/widget-creator-agent.ts +0 -568
  50. package/src/api/error-handling.ts +0 -1758
  51. package/src/api/natural-language-mapper.ts +0 -630
  52. package/src/api/performance-optimizer.ts +0 -891
  53. package/src/api/transaction-manager.ts +0 -754
  54. package/src/cli/deploy-artifact.ts +0 -304
  55. package/src/cli/snow-flow-cli-integration.ts +0 -434
  56. package/src/cli.ts +0 -4455
  57. package/src/cli.ts.bak +0 -5616
  58. package/src/compliance/advanced-compliance-system.ts +0 -1268
  59. package/src/compliance/index.ts +0 -19
  60. package/src/config/snow-flow-config.ts +0 -1019
  61. package/src/documentation/index.ts +0 -16
  62. package/src/documentation/self-documenting-system.ts +0 -1421
  63. package/src/dynamic-version.ts +0 -44
  64. package/src/healing/index.ts +0 -20
  65. package/src/healing/self-healing-system.ts +0 -1435
  66. package/src/health/README.md +0 -161
  67. package/src/health/system-health.ts +0 -995
  68. package/src/index.ts +0 -60
  69. package/src/intelligence/acl-analyzer.ts +0 -377
  70. package/src/intelligence/auto-resolution-engine.ts +0 -643
  71. package/src/intelligence/gap-analysis-engine.ts +0 -488
  72. package/src/intelligence/manual-instructions-generator.ts +0 -744
  73. package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
  74. package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
  75. package/src/intelligence/performance-recommendations-engine.ts +0 -1223
  76. package/src/intelligence/requirements-analyzer.ts +0 -1148
  77. package/src/intelligence/task-analyzer.ts +0 -628
  78. package/src/managers/scope-manager.ts +0 -555
  79. package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
  80. package/src/mcp/base-mcp-server.ts +0 -660
  81. package/src/mcp/http-transport-wrapper.ts +0 -426
  82. package/src/mcp/service-discovery-client.ts +0 -312
  83. package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
  84. package/src/mcp/servicenow-automation-mcp.ts +0 -838
  85. package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
  86. package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
  87. package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
  88. package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
  89. package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
  90. package/src/mcp/servicenow-integration-mcp.ts +0 -819
  91. package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
  92. package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
  93. package/src/mcp/servicenow-mcp-server.ts +0 -728
  94. package/src/mcp/servicenow-memory-mcp.ts +0 -474
  95. package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
  96. package/src/mcp/servicenow-operations-mcp.ts +0 -3384
  97. package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
  98. package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
  99. package/src/mcp/servicenow-progressive-indexer.ts +0 -370
  100. package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
  101. package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
  102. package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
  103. package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
  104. package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
  105. package/src/mcp/servicenow-update-set-mcp.ts +0 -811
  106. package/src/mcp/shared/agent-context-provider.ts +0 -365
  107. package/src/mcp/shared/base-mcp-server.ts +0 -2463
  108. package/src/mcp/shared/mcp-memory-manager.ts +0 -540
  109. package/src/mcp/shared/mcp-resource-manager.ts +0 -367
  110. package/src/mcp/snow-flow-mcp.ts +0 -911
  111. package/src/mcp/start-all-mcp-servers.ts +0 -102
  112. package/src/mcp/start-servicenow-mcp.ts +0 -67
  113. package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
  114. package/src/monitoring/performance-tracker.ts +0 -777
  115. package/src/optimization/cost-optimization-engine.ts +0 -1125
  116. package/src/optimization/index.ts +0 -10
  117. package/src/queen/README.md +0 -403
  118. package/src/queen/agent-factory.ts +0 -574
  119. package/src/queen/index.ts +0 -94
  120. package/src/queen/mcp-execution-bridge.ts +0 -681
  121. package/src/queen/neural-learning.ts +0 -319
  122. package/src/queen/parallel-agent-engine.ts +0 -848
  123. package/src/queen/queen-memory-system.ts +0 -490
  124. package/src/queen/queen-memory.ts +0 -456
  125. package/src/queen/servicenow-queen.ts +0 -1029
  126. package/src/queen/types.ts +0 -87
  127. package/src/rollback/smart-rollback-system.ts +0 -866
  128. package/src/schemas/deployment.schema.json +0 -58
  129. package/src/schemas/flow.schema.json +0 -79
  130. package/src/schemas/widget.schema.json +0 -72
  131. package/src/snow-flow-system.ts +0 -541
  132. package/src/sparc/sparc-help.ts +0 -49
  133. package/src/sparc/team-sparc.ts +0 -88
  134. package/src/strategies/global-scope-strategy.ts +0 -736
  135. package/src/templates/base/application.template.json +0 -45
  136. package/src/templates/base/business_rule.template.json +0 -33
  137. package/src/templates/base/script_include.template.json +0 -18
  138. package/src/templates/base/table.template.json +0 -64
  139. package/src/templates/base/widget.template.json +0 -25
  140. package/src/templates/patterns/composite.incident-management.template.json +0 -140
  141. package/src/templates/patterns/widget.dashboard.template.json +0 -238
  142. package/src/templates/patterns/widget.datatable.template.json +0 -292
  143. package/src/testing/integration-test-suite.ts +0 -1276
  144. package/src/types/index.ts +0 -183
  145. package/src/types/neo4j-driver.d.ts +0 -23
  146. package/src/types/servicenow.types.ts +0 -307
  147. package/src/types/snow-flow.types.ts +0 -186
  148. package/src/types/todo.types.ts +0 -70
  149. package/src/utils/action-type-cache.ts +0 -286
  150. package/src/utils/agent-detector.ts +0 -573
  151. package/src/utils/artifact-tracker.ts +0 -379
  152. package/src/utils/dependency-detector.ts +0 -233
  153. package/src/utils/deployment-metadata-handler.ts +0 -518
  154. package/src/utils/error-recovery.ts +0 -680
  155. package/src/utils/logger.ts +0 -60
  156. package/src/utils/mcp-auth-middleware.ts +0 -262
  157. package/src/utils/mcp-config-manager.ts +0 -270
  158. package/src/utils/mcp-server-manager.ts +0 -446
  159. package/src/utils/mcp-tool-registry.ts +0 -298
  160. package/src/utils/migrate-snow-flow.ts +0 -98
  161. package/src/utils/oauth-html-templates.ts +0 -188
  162. package/src/utils/scope-utils.ts +0 -443
  163. package/src/utils/servicenow-client.ts +0 -3321
  164. package/src/utils/servicenow-id-generator.ts +0 -181
  165. package/src/utils/snow-memory-manager.ts +0 -605
  166. package/src/utils/snow-oauth.ts +0 -797
  167. package/src/utils/template-engine.ts +0 -463
  168. package/src/utils/theme-manager.ts +0 -295
  169. package/src/utils/unified-auth-store.ts +0 -222
  170. package/src/utils/update-set-importer.ts +0 -422
  171. package/src/utils/update-set-xml-packager.ts +0 -371
  172. package/src/utils/widget-template-generator.ts +0 -1744
  173. package/src/version.ts +0 -1950
@@ -1,970 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * ServiceNow Platform Development MCP Server
4
- * Handles core platform development artifacts with full dynamic discovery
5
- * NO HARDCODED VALUES - All tables, fields, and configurations discovered dynamically
6
- */
7
-
8
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import {
11
- CallToolRequestSchema,
12
- ErrorCode,
13
- ListToolsRequestSchema,
14
- McpError,
15
- } from '@modelcontextprotocol/sdk/types.js';
16
- import { ServiceNowClient } from '../utils/servicenow-client.js';
17
- import { mcpAuth } from '../utils/mcp-auth-middleware.js';
18
- import { mcpConfig } from '../utils/mcp-config-manager.js';
19
- import { Logger } from '../utils/logger.js';
20
-
21
- interface PlatformArtifactType {
22
- table: string;
23
- name: string;
24
- description: string;
25
- primaryFields: string[];
26
- requiredFields: string[];
27
- deploymentFields: string[];
28
- }
29
-
30
- interface DynamicTableInfo {
31
- name: string;
32
- label: string;
33
- fields: Array<{
34
- name: string;
35
- type: string;
36
- label: string;
37
- mandatory: boolean;
38
- display: boolean;
39
- }>;
40
- }
41
-
42
- class ServiceNowPlatformDevelopmentMCP {
43
- private server: Server;
44
- private client: ServiceNowClient;
45
- private logger: Logger;
46
- private config: ReturnType<typeof mcpConfig.getConfig>;
47
- private tableCache: Map<string, DynamicTableInfo> = new Map();
48
-
49
- constructor() {
50
- this.server = new Server(
51
- {
52
- name: 'servicenow-platform-development',
53
- version: '1.0.0',
54
- },
55
- {
56
- capabilities: {
57
- tools: {},
58
- },
59
- }
60
- );
61
-
62
- this.client = new ServiceNowClient();
63
- this.logger = new Logger('ServiceNowPlatformDevelopmentMCP');
64
- this.config = mcpConfig.getConfig();
65
-
66
- this.setupHandlers();
67
- }
68
-
69
- private setupHandlers() {
70
- this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
71
- tools: [
72
- {
73
- name: 'snow_create_ui_page',
74
- description: 'Create UI Pages dynamically with full field discovery - NO hardcoded values',
75
- inputSchema: {
76
- type: 'object',
77
- properties: {
78
- name: { type: 'string', description: 'UI Page name' },
79
- title: { type: 'string', description: 'Page title' },
80
- html: { type: 'string', description: 'HTML content' },
81
- processingScript: { type: 'string', description: 'Server-side processing script' },
82
- clientScript: { type: 'string', description: 'Client-side script' },
83
- css: { type: 'string', description: 'CSS styles' },
84
- category: { type: 'string', description: 'Page category' }
85
- },
86
- required: ['name', 'title', 'html']
87
- }
88
- },
89
- {
90
- name: 'snow_create_script_include',
91
- description: 'Create Script Includes with dynamic table discovery - NO hardcoded values',
92
- inputSchema: {
93
- type: 'object',
94
- properties: {
95
- name: { type: 'string', description: 'Script Include name' },
96
- script: { type: 'string', description: 'JavaScript code' },
97
- description: { type: 'string', description: 'Description of functionality' },
98
- clientCallable: { type: 'boolean', description: 'Can be called from client' },
99
- apiName: { type: 'string', description: 'API name for external calls' }
100
- },
101
- required: ['name', 'script']
102
- }
103
- },
104
- {
105
- name: 'snow_create_business_rule',
106
- description: 'Create Business Rules with dynamic table and field discovery - NO hardcoded values',
107
- inputSchema: {
108
- type: 'object',
109
- properties: {
110
- name: { type: 'string', description: 'Business Rule name' },
111
- tableName: { type: 'string', description: 'Target table name or sys_id' },
112
- script: { type: 'string', description: 'JavaScript code' },
113
- when: { type: 'string', description: 'When to execute: before, after, async, display' },
114
- condition: { type: 'string', description: 'Condition script' },
115
- description: { type: 'string', description: 'Rule description' }
116
- },
117
- required: ['name', 'tableName', 'script', 'when']
118
- }
119
- },
120
- {
121
- name: 'snow_create_client_script',
122
- description: 'Create Client Scripts with dynamic form discovery - NO hardcoded values',
123
- inputSchema: {
124
- type: 'object',
125
- properties: {
126
- name: { type: 'string', description: 'Client Script name' },
127
- tableName: { type: 'string', description: 'Target table name or sys_id' },
128
- script: { type: 'string', description: 'JavaScript code' },
129
- type: { type: 'string', description: 'Script type: onLoad, onChange, onSubmit, onCellEdit' },
130
- fieldName: { type: 'string', description: 'Field name for onChange scripts' },
131
- condition: { type: 'string', description: 'Condition script' },
132
- description: { type: 'string', description: 'Script description' }
133
- },
134
- required: ['name', 'tableName', 'script', 'type']
135
- }
136
- },
137
- {
138
- name: 'snow_create_ui_policy',
139
- description: 'Create UI Policies with dynamic field discovery - NO hardcoded values',
140
- inputSchema: {
141
- type: 'object',
142
- properties: {
143
- name: { type: 'string', description: 'UI Policy name' },
144
- tableName: { type: 'string', description: 'Target table name or sys_id' },
145
- condition: { type: 'string', description: 'Condition script' },
146
- description: { type: 'string', description: 'Policy description' },
147
- runScripts: { type: 'boolean', description: 'Run scripts when policy applies' },
148
- reverseWhenFalse: { type: 'boolean', description: 'Reverse actions when condition is false' }
149
- },
150
- required: ['name', 'tableName', 'condition']
151
- }
152
- },
153
- {
154
- name: 'snow_create_ui_action',
155
- description: 'Create UI Actions with dynamic form discovery - NO hardcoded values',
156
- inputSchema: {
157
- type: 'object',
158
- properties: {
159
- name: { type: 'string', description: 'UI Action name' },
160
- tableName: { type: 'string', description: 'Target table name or sys_id' },
161
- script: { type: 'string', description: 'JavaScript code' },
162
- condition: { type: 'string', description: 'Condition script' },
163
- actionName: { type: 'string', description: 'Action name for forms' },
164
- formButton: { type: 'boolean', description: 'Show as form button' },
165
- listButton: { type: 'boolean', description: 'Show as list button' },
166
- description: { type: 'string', description: 'Action description' }
167
- },
168
- required: ['name', 'tableName', 'script']
169
- }
170
- },
171
- {
172
- name: 'snow_discover_platform_tables',
173
- description: 'Discover all available platform development tables dynamically',
174
- inputSchema: {
175
- type: 'object',
176
- properties: {
177
- category: { type: 'string', description: 'Filter by category: ui, script, policy, action, all' }
178
- }
179
- }
180
- },
181
- {
182
- name: 'snow_discover_table_fields',
183
- description: 'Discover all fields for a specific table dynamically',
184
- inputSchema: {
185
- type: 'object',
186
- properties: {
187
- tableName: { type: 'string', description: 'Table name to discover fields for' }
188
- },
189
- required: ['tableName']
190
- }
191
- },
192
- {
193
- name: 'snow_table_schema_discovery',
194
- description: 'Comprehensive table schema discovery - structure, relationships, indexes, constraints',
195
- inputSchema: {
196
- type: 'object',
197
- properties: {
198
- tableName: { type: 'string', description: 'Table name to analyze' },
199
- includeRelated: { type: 'boolean', description: 'Include related table information' },
200
- includeIndexes: { type: 'boolean', description: 'Include index information' },
201
- includeExtensions: { type: 'boolean', description: 'Include table extensions/hierarchy' },
202
- maxDepth: { type: 'number', description: 'Max depth for relationship discovery (default: 2)' }
203
- },
204
- required: ['tableName']
205
- }
206
- }
207
- ]
208
- }));
209
-
210
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
211
- try {
212
- const { name, arguments: args } = request.params;
213
-
214
- // Ensure authentication
215
- const authResult = await mcpAuth.ensureAuthenticated();
216
- if (!authResult.success) {
217
- throw new McpError(
218
- ErrorCode.InternalError,
219
- authResult.error || 'Authentication required'
220
- );
221
- }
222
-
223
- switch (name) {
224
- case 'snow_create_ui_page':
225
- return await this.createUIPage(args);
226
- case 'snow_create_script_include':
227
- return await this.createScriptInclude(args);
228
- case 'snow_create_business_rule':
229
- return await this.createBusinessRule(args);
230
- case 'snow_create_client_script':
231
- return await this.createClientScript(args);
232
- case 'snow_create_ui_policy':
233
- return await this.createUIPolicy(args);
234
- case 'snow_create_ui_action':
235
- return await this.createUIAction(args);
236
- case 'snow_discover_platform_tables':
237
- return await this.discoverPlatformTables(args);
238
- case 'snow_discover_table_fields':
239
- return await this.discoverTableFields(args);
240
- case 'snow_table_schema_discovery':
241
- return await this.discoverTableSchema(args);
242
- default:
243
- throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
244
- }
245
- } catch (error) {
246
- this.logger.error(`Error in ${request.params.name}:`, error);
247
- throw error;
248
- }
249
- });
250
- }
251
-
252
- /**
253
- * Dynamically discover all platform development tables
254
- */
255
- private async discoverPlatformTables(args: any) {
256
- try {
257
- this.logger.info('Discovering platform development tables...');
258
-
259
- // Define table categories based on actual ServiceNow schema
260
- const tableQueries = [
261
- { category: 'ui', query: 'nameSTARTSWITHsys_ui^ORnameSTARTSWITHsp_' },
262
- { category: 'script', query: 'nameSTARTSWITHsys_script^ORnameSTARTSWITHsys_processor' },
263
- { category: 'policy', query: 'nameSTARTSWITHsys_ui_policy^ORnameSTARTSWITHsys_ui_action' },
264
- { category: 'security', query: 'nameSTARTSWITHsys_security^ORnameSTARTSWITHsys_user' },
265
- { category: 'system', query: 'nameSTARTSWITHsys_dictionary^ORnameSTARTSWITHsys_choice' }
266
- ];
267
-
268
- const category = args?.category || 'all';
269
- const discoveredTables: Array<{category: string, tables: any[]}> = [];
270
-
271
- for (const tableQuery of tableQueries) {
272
- if (category === 'all' || category === tableQuery.category) {
273
- const tablesResponse = await this.client.searchRecords(
274
- 'sys_db_object',
275
- tableQuery.query,
276
- 50
277
- );
278
-
279
- if (tablesResponse.success && tablesResponse.data) {
280
- discoveredTables.push({
281
- category: tableQuery.category,
282
- tables: tablesResponse.data.result.map((table: any) => ({
283
- name: table.name,
284
- label: table.label,
285
- super_class: table.super_class,
286
- is_extendable: table.is_extendable,
287
- sys_id: table.sys_id
288
- }))
289
- });
290
- }
291
- }
292
- }
293
-
294
- return {
295
- content: [{
296
- type: 'text',
297
- text: `šŸ” Discovered Platform Development Tables:\n\n${discoveredTables.map(cat =>
298
- `**${cat.category.toUpperCase()} Tables:**\n${cat.tables.map(table =>
299
- `- ${table.name} (${table.label})`
300
- ).join('\n')}`
301
- ).join('\n\n')}\n\n✨ All tables discovered dynamically from ServiceNow schema - no hardcoded values!`
302
- }]
303
- };
304
- } catch (error) {
305
- this.logger.error('Failed to discover platform tables:', error);
306
- throw new McpError(ErrorCode.InternalError, `Failed to discover tables: ${error}`);
307
- }
308
- }
309
-
310
- /**
311
- * Dynamically discover table fields
312
- */
313
- private async discoverTableFields(args: any) {
314
- try {
315
- const tableName = args.tableName;
316
- this.logger.info(`Discovering fields for table: ${tableName}`);
317
-
318
- // First, resolve table name to sys_id if needed
319
- const tableInfo = await this.getTableInfo(tableName);
320
- if (!tableInfo) {
321
- throw new Error(`Table not found: ${tableName}`);
322
- }
323
-
324
- // Get all fields for this table
325
- const fieldsResponse = await this.client.searchRecords(
326
- 'sys_dictionary',
327
- `nameSTARTSWITH${tableInfo.name}^element!=NULL`,
328
- 100
329
- );
330
-
331
- if (!fieldsResponse.success || !fieldsResponse.data) {
332
- throw new Error(`Failed to get fields for table: ${tableName}`);
333
- }
334
-
335
- const fields = fieldsResponse.data.result.map((field: any) => ({
336
- name: field.element,
337
- type: field.internal_type,
338
- label: field.column_label,
339
- mandatory: field.mandatory === 'true',
340
- display: field.display === 'true',
341
- max_length: field.max_length,
342
- reference: field.reference,
343
- choice: field.choice
344
- }));
345
-
346
- // Cache the table info
347
- this.tableCache.set(tableName, {
348
- name: tableInfo.name,
349
- label: tableInfo.label,
350
- fields: fields
351
- });
352
-
353
- return {
354
- content: [{
355
- type: 'text',
356
- text: `šŸ“‹ Fields for ${tableInfo.label} (${tableInfo.name}):\n\n${fields.map((field: any) =>
357
- `- **${field.name}** (${field.label})\n Type: ${field.type}${field.mandatory ? ' *Required*' : ''}${field.reference ? ` -> ${field.reference}` : ''}`
358
- ).join('\n')}\n\nšŸ” Total fields: ${fields.length}\n✨ All fields discovered dynamically from ServiceNow schema!`
359
- }]
360
- };
361
- } catch (error) {
362
- this.logger.error('Failed to discover table fields:', error);
363
- throw new McpError(ErrorCode.InternalError, `Failed to discover fields: ${error}`);
364
- }
365
- }
366
-
367
- /**
368
- * Get table information dynamically
369
- */
370
- private async getTableInfo(tableName: string): Promise<{name: string, label: string, sys_id: string} | null> {
371
- try {
372
- this.logger.debug(`Looking up table info for: ${tableName}`);
373
-
374
- // First, check if this is a known standard table that may not appear in sys_db_object
375
- const standardTables: Record<string, {label: string}> = {
376
- 'incident': { label: 'Incident' },
377
- 'problem': { label: 'Problem' },
378
- 'change_request': { label: 'Change Request' },
379
- 'sc_request': { label: 'Request' },
380
- 'sc_req_item': { label: 'Requested Item' },
381
- 'sc_task': { label: 'Catalog Task' },
382
- 'task': { label: 'Task' }
383
- };
384
-
385
- if (standardTables[tableName]) {
386
- this.logger.debug(`Using known standard table: ${tableName}`);
387
- return {
388
- name: tableName,
389
- label: standardTables[tableName].label,
390
- sys_id: `standard_table_${tableName}` // Placeholder sys_id for standard tables
391
- };
392
- }
393
-
394
- // Try direct lookup first
395
- const tableResponse = await this.client.searchRecords(
396
- 'sys_db_object',
397
- `name=${tableName}`,
398
- 1
399
- );
400
-
401
- if (tableResponse.success && tableResponse.data?.result?.length > 0) {
402
- const table = tableResponse.data.result[0];
403
- return {
404
- name: table.name,
405
- label: table.label,
406
- sys_id: table.sys_id
407
- };
408
- }
409
-
410
- // Log the actual response for debugging
411
- this.logger.debug(`Table lookup response for ${tableName}: ${JSON.stringify(tableResponse)}`);
412
-
413
- // Try by sys_id
414
- const tableByIdResponse = await this.client.searchRecords(
415
- 'sys_db_object',
416
- `sys_id=${tableName}`,
417
- 1
418
- );
419
-
420
- if (tableByIdResponse.success && tableByIdResponse.data?.result?.length > 0) {
421
- const table = tableByIdResponse.data.result[0];
422
- return {
423
- name: table.name,
424
- label: table.label,
425
- sys_id: table.sys_id
426
- };
427
- }
428
-
429
- // Try partial match
430
- const tableByPartialResponse = await this.client.searchRecords(
431
- 'sys_db_object',
432
- `nameCONTAINS${tableName}^ORlabelCONTAINS${tableName}`,
433
- 5
434
- );
435
-
436
- if (tableByPartialResponse.success && tableByPartialResponse.data?.result?.length > 0) {
437
- const table = tableByPartialResponse.data.result[0];
438
- return {
439
- name: table.name,
440
- label: table.label,
441
- sys_id: table.sys_id
442
- };
443
- }
444
-
445
- return null;
446
- } catch (error) {
447
- this.logger.error(`Failed to get table info for ${tableName}:`, error);
448
- return null;
449
- }
450
- }
451
-
452
- /**
453
- * Create UI Page with dynamic field discovery
454
- */
455
- private async createUIPage(args: any) {
456
- try {
457
- this.logger.info('Creating UI Page...');
458
-
459
- // Get UI Page table structure dynamically
460
- const uiPageFields = await this.discoverRequiredFields('sys_ui_page');
461
-
462
- const uiPageData = {
463
- name: args.name,
464
- title: args.title,
465
- html: args.html,
466
- processing_script: args.processingScript || '',
467
- client_script: args.clientScript || '',
468
- css: args.css || '',
469
- category: args.category || 'general'
470
- };
471
-
472
- // Ensure we have Update Set
473
- const updateSetResult = await this.client.ensureUpdateSet();
474
-
475
- const response = await this.client.createRecord('sys_ui_page', uiPageData);
476
-
477
- if (!response.success) {
478
- throw new Error(`Failed to create UI Page: ${response.error}`);
479
- }
480
-
481
- return {
482
- content: [{
483
- type: 'text',
484
- text: `āœ… UI Page created successfully!\n\nšŸ“„ **${args.title}** (${args.name})\nšŸ†” sys_id: ${response.data.sys_id}\n\nšŸ”— View in ServiceNow: Open UI Page editor\n\n✨ Created with dynamic field discovery - no hardcoded values!`
485
- }]
486
- };
487
- } catch (error) {
488
- this.logger.error('Failed to create UI Page:', error);
489
- throw new McpError(ErrorCode.InternalError, `Failed to create UI Page: ${error}`);
490
- }
491
- }
492
-
493
- /**
494
- * Create Script Include with dynamic discovery
495
- */
496
- private async createScriptInclude(args: any) {
497
- try {
498
- this.logger.info('Creating Script Include...');
499
-
500
- const scriptIncludeData = {
501
- name: args.name,
502
- script: args.script,
503
- description: args.description || '',
504
- client_callable: args.clientCallable || false,
505
- api_name: args.apiName || args.name
506
- };
507
-
508
- const updateSetResult = await this.client.ensureUpdateSet();
509
- const response = await this.client.createRecord('sys_script_include', scriptIncludeData);
510
-
511
- if (!response.success) {
512
- throw new Error(`Failed to create Script Include: ${response.error}`);
513
- }
514
-
515
- return {
516
- content: [{
517
- type: 'text',
518
- text: `āœ… Script Include created successfully!\n\nšŸ“œ **${args.name}**\nšŸ†” sys_id: ${response.data.sys_id}\nšŸ”§ Client Callable: ${args.clientCallable ? 'Yes' : 'No'}\n\nšŸ“ Description: ${args.description || 'No description provided'}\n\n✨ Created with dynamic field discovery!`
519
- }]
520
- };
521
- } catch (error) {
522
- this.logger.error('Failed to create Script Include:', error);
523
- throw new McpError(ErrorCode.InternalError, `Failed to create Script Include: ${error}`);
524
- }
525
- }
526
-
527
- /**
528
- * Create Business Rule with dynamic table discovery
529
- */
530
- private async createBusinessRule(args: any) {
531
- try {
532
- this.logger.info('Creating Business Rule...');
533
-
534
- // Resolve table name dynamically
535
- const tableInfo = await this.getTableInfo(args.tableName);
536
- if (!tableInfo) {
537
- throw new Error(`Table not found: ${args.tableName}`);
538
- }
539
-
540
- const businessRuleData = {
541
- name: args.name,
542
- table: tableInfo.name,
543
- script: args.script,
544
- when: args.when,
545
- condition: args.condition || '',
546
- description: args.description || ''
547
- };
548
-
549
- const updateSetResult = await this.client.ensureUpdateSet();
550
- const response = await this.client.createRecord('sys_script', businessRuleData);
551
-
552
- if (!response.success) {
553
- throw new Error(`Failed to create Business Rule: ${response.error}`);
554
- }
555
-
556
- return {
557
- content: [{
558
- type: 'text',
559
- text: `āœ… Business Rule created successfully!\n\nšŸ“‹ **${args.name}**\nšŸ†” sys_id: ${response.data.sys_id}\nšŸ“Š Table: ${tableInfo.label} (${tableInfo.name})\nā° When: ${args.when}\n\nšŸ“ Description: ${args.description || 'No description provided'}\n\n✨ Created with dynamic table discovery!`
560
- }]
561
- };
562
- } catch (error) {
563
- this.logger.error('Failed to create Business Rule:', error);
564
- throw new McpError(ErrorCode.InternalError, `Failed to create Business Rule: ${error}`);
565
- }
566
- }
567
-
568
- /**
569
- * Create Client Script with dynamic discovery
570
- */
571
- private async createClientScript(args: any) {
572
- try {
573
- this.logger.info('Creating Client Script...');
574
-
575
- const tableInfo = await this.getTableInfo(args.tableName);
576
- if (!tableInfo) {
577
- throw new Error(`Table not found: ${args.tableName}`);
578
- }
579
-
580
- const clientScriptData = {
581
- name: args.name,
582
- table: tableInfo.name,
583
- script: args.script,
584
- type: args.type,
585
- field: args.fieldName || '',
586
- condition: args.condition || '',
587
- description: args.description || ''
588
- };
589
-
590
- const updateSetResult = await this.client.ensureUpdateSet();
591
- const response = await this.client.createRecord('sys_script_client', clientScriptData);
592
-
593
- if (!response.success) {
594
- throw new Error(`Failed to create Client Script: ${response.error}`);
595
- }
596
-
597
- return {
598
- content: [{
599
- type: 'text',
600
- text: `āœ… Client Script created successfully!\n\nšŸ“œ **${args.name}**\nšŸ†” sys_id: ${response.data.sys_id}\nšŸ“Š Table: ${tableInfo.label} (${tableInfo.name})\nšŸ”§ Type: ${args.type}\n${args.fieldName ? `šŸ·ļø Field: ${args.fieldName}\n` : ''}\nšŸ“ Description: ${args.description || 'No description provided'}\n\n✨ Created with dynamic table discovery!`
601
- }]
602
- };
603
- } catch (error) {
604
- this.logger.error('Failed to create Client Script:', error);
605
- throw new McpError(ErrorCode.InternalError, `Failed to create Client Script: ${error}`);
606
- }
607
- }
608
-
609
- /**
610
- * Create UI Policy with dynamic discovery
611
- */
612
- private async createUIPolicy(args: any) {
613
- try {
614
- this.logger.info('Creating UI Policy...');
615
-
616
- const tableInfo = await this.getTableInfo(args.tableName);
617
- if (!tableInfo) {
618
- throw new Error(`Table not found: ${args.tableName}`);
619
- }
620
-
621
- const uiPolicyData = {
622
- name: args.name,
623
- table: tableInfo.name,
624
- conditions: args.condition,
625
- description: args.description || '',
626
- run_scripts: args.runScripts || false,
627
- reverse_if_false: args.reverseWhenFalse || false
628
- };
629
-
630
- const updateSetResult = await this.client.ensureUpdateSet();
631
- const response = await this.client.createRecord('sys_ui_policy', uiPolicyData);
632
-
633
- if (!response.success) {
634
- throw new Error(`Failed to create UI Policy: ${response.error}`);
635
- }
636
-
637
- return {
638
- content: [{
639
- type: 'text',
640
- text: `āœ… UI Policy created successfully!\n\nšŸ“‹ **${args.name}**\nšŸ†” sys_id: ${response.data.sys_id}\nšŸ“Š Table: ${tableInfo.label} (${tableInfo.name})\nšŸ”§ Run Scripts: ${args.runScripts ? 'Yes' : 'No'}\n\nšŸ“ Description: ${args.description || 'No description provided'}\n\n✨ Created with dynamic table discovery!`
641
- }]
642
- };
643
- } catch (error) {
644
- this.logger.error('Failed to create UI Policy:', error);
645
- throw new McpError(ErrorCode.InternalError, `Failed to create UI Policy: ${error}`);
646
- }
647
- }
648
-
649
- /**
650
- * Create UI Action with dynamic discovery
651
- */
652
- private async createUIAction(args: any) {
653
- try {
654
- this.logger.info('Creating UI Action...');
655
-
656
- const tableInfo = await this.getTableInfo(args.tableName);
657
- if (!tableInfo) {
658
- throw new Error(`Table not found: ${args.tableName}`);
659
- }
660
-
661
- const uiActionData = {
662
- name: args.name,
663
- table: tableInfo.name,
664
- script: args.script,
665
- condition: args.condition || '',
666
- action_name: args.actionName || args.name,
667
- form_button: args.formButton || false,
668
- list_button: args.listButton || false,
669
- description: args.description || ''
670
- };
671
-
672
- const updateSetResult = await this.client.ensureUpdateSet();
673
- const response = await this.client.createRecord('sys_ui_action', uiActionData);
674
-
675
- if (!response.success) {
676
- throw new Error(`Failed to create UI Action: ${response.error}`);
677
- }
678
-
679
- return {
680
- content: [{
681
- type: 'text',
682
- text: `āœ… UI Action created successfully!\n\nšŸŽÆ **${args.name}**\nšŸ†” sys_id: ${response.data.sys_id}\nšŸ“Š Table: ${tableInfo.label} (${tableInfo.name})\nšŸ”˜ Form Button: ${args.formButton ? 'Yes' : 'No'}\nšŸ“ List Button: ${args.listButton ? 'Yes' : 'No'}\n\nšŸ“ Description: ${args.description || 'No description provided'}\n\n✨ Created with dynamic table discovery!`
683
- }]
684
- };
685
- } catch (error) {
686
- this.logger.error('Failed to create UI Action:', error);
687
- throw new McpError(ErrorCode.InternalError, `Failed to create UI Action: ${error}`);
688
- }
689
- }
690
-
691
- /**
692
- * Discover required fields for a table dynamically
693
- */
694
- private async discoverRequiredFields(tableName: string): Promise<string[]> {
695
- try {
696
- const fieldsResponse = await this.client.searchRecords(
697
- 'sys_dictionary',
698
- `nameSTARTSWITH${tableName}^element!=NULL^mandatory=true`,
699
- 50
700
- );
701
-
702
- if (fieldsResponse.success && fieldsResponse.data) {
703
- return fieldsResponse.data.result.map((field: any) => field.element);
704
- }
705
-
706
- return [];
707
- } catch (error) {
708
- this.logger.error(`Failed to discover required fields for ${tableName}:`, error);
709
- return [];
710
- }
711
- }
712
-
713
- /**
714
- * Comprehensive table schema discovery
715
- */
716
- private async discoverTableSchema(args: any) {
717
- try {
718
- const { tableName, includeRelated = true, includeIndexes = true, includeExtensions = true, maxDepth = 2 } = args;
719
- this.logger.info(`Discovering comprehensive schema for table: ${tableName}`);
720
-
721
- // Validate authentication
722
- if (!this.client) {
723
- throw new Error('ServiceNow client not initialized');
724
- }
725
-
726
- // Get table information
727
- const tableInfo = await this.getTableInfo(tableName);
728
- if (!tableInfo) {
729
- throw new Error(`Table not found: ${tableName}. Searched in sys_db_object table.`);
730
- }
731
-
732
- this.logger.debug(`Found table info: ${JSON.stringify(tableInfo)}`);
733
-
734
- // Get detailed table metadata
735
- this.logger.debug(`Attempting to fetch table details for sys_id: ${tableInfo.sys_id}`);
736
-
737
- // Check if this is a standard table with placeholder sys_id
738
- const isStandardTable = tableInfo.sys_id.startsWith('standard_table_');
739
- let tableDetailsResponse: any = { success: false };
740
-
741
- if (!isStandardTable) {
742
- tableDetailsResponse = await this.client.getRecord('sys_db_object', tableInfo.sys_id);
743
- }
744
-
745
- // Declare the variable once with proper type
746
- let tableDetails: any;
747
-
748
- if (!tableDetailsResponse.success || isStandardTable) {
749
- const errorMessage = tableDetailsResponse.error ||
750
- JSON.stringify(tableDetailsResponse) ||
751
- 'Unknown error occurred while fetching table details';
752
- this.logger.error(`Table details fetch failed for ${tableInfo.sys_id}:`, tableDetailsResponse);
753
-
754
- // Fallback: try using basic table info if detailed fetch fails
755
- this.logger.warn(`Falling back to basic table info for ${tableInfo.name}`);
756
- tableDetails = {
757
- name: tableInfo.name,
758
- label: tableInfo.label,
759
- sys_id: tableInfo.sys_id,
760
- is_extendable: 'unknown',
761
- access: 'unknown',
762
- sys_created_on: 'unknown',
763
- sys_updated_on: 'unknown',
764
- row_count: 'unknown',
765
- super_class: null,
766
- extension_model: 'unknown',
767
- sys_scope: null
768
- };
769
- } else {
770
- tableDetails = tableDetailsResponse.data;
771
- }
772
-
773
- // Get all fields with detailed information
774
- const fieldsResponse = await this.client.searchRecords(
775
- 'sys_dictionary',
776
- `name=${tableInfo.name}^element!=NULL`,
777
- 200
778
- );
779
-
780
- if (!fieldsResponse.success || !fieldsResponse.data) {
781
- const errorMessage = fieldsResponse.error ||
782
- 'No data returned from fields query' ||
783
- JSON.stringify(fieldsResponse);
784
- this.logger.error(`Fields fetch failed for ${tableInfo.name}:`, fieldsResponse);
785
- throw new Error(`Failed to get fields for table ${tableName}: ${errorMessage}`);
786
- }
787
-
788
- const fields = fieldsResponse.data.result.map((field: any) => ({
789
- name: field.element,
790
- label: field.column_label,
791
- type: field.internal_type,
792
- dataType: field.internal_type,
793
- maxLength: field.max_length,
794
- mandatory: field.mandatory === 'true',
795
- readOnly: field.read_only === 'true',
796
- display: field.display === 'true',
797
- active: field.active === 'true',
798
- array: field.array === 'true',
799
- reference: field.reference,
800
- referenceQual: field.reference_qual,
801
- defaultValue: field.default_value,
802
- choice: field.choice,
803
- calculated: field.virtual === 'true',
804
- attributes: field.attributes,
805
- comments: field.comments
806
- }));
807
-
808
- // Analyze relationships
809
- const relationships = fields
810
- .filter((field: any) => field.reference)
811
- .map((field: any) => ({
812
- field: field.name,
813
- targetTable: field.reference,
814
- label: field.label,
815
- referenceQual: field.referenceQual
816
- }));
817
-
818
- // Get table hierarchy if requested
819
- let hierarchy: any = null;
820
- if (includeExtensions) {
821
- hierarchy = {
822
- extends: tableDetails.super_class?.display_value || null,
823
- extendsTable: tableDetails.super_class?.value || null,
824
- isExtendable: tableDetails.is_extendable === 'true',
825
- extensionModel: tableDetails.extension_model
826
- };
827
-
828
- // Find tables that extend this one
829
- const childTablesResponse = await this.client.searchRecords(
830
- 'sys_db_object',
831
- `super_class=${tableInfo.sys_id}`,
832
- 50
833
- );
834
-
835
- if (childTablesResponse.success && childTablesResponse.data) {
836
- hierarchy.extendedBy = childTablesResponse.data.result.map((child: any) => ({
837
- name: child.name,
838
- label: child.label,
839
- sys_id: child.sys_id
840
- }));
841
- }
842
- }
843
-
844
- // Get indexes if requested
845
- let indexes: any[] = [];
846
- if (includeIndexes) {
847
- const indexResponse = await this.client.searchRecords(
848
- 'sys_db_index',
849
- `table=${tableInfo.sys_id}`,
850
- 50
851
- );
852
-
853
- if (indexResponse.success && indexResponse.data) {
854
- indexes = indexResponse.data.result.map((index: any) => ({
855
- name: index.name,
856
- unique: index.unique === 'true',
857
- clustered: index.clustered === 'true',
858
- fields: index.fields
859
- }));
860
- }
861
- }
862
-
863
- // Get related tables if requested
864
- const relatedTables: any[] = [];
865
- if (includeRelated && relationships.length > 0) {
866
- const uniqueRelatedTables = [...new Set(relationships.map((rel: any) => rel.targetTable))];
867
-
868
- for (const relTable of uniqueRelatedTables.slice(0, 10)) { // Limit to prevent too many queries
869
- const relTableInfo = await this.getTableInfo(String(relTable));
870
- if (relTableInfo) {
871
- relatedTables.push({
872
- name: relTableInfo.name,
873
- label: relTableInfo.label,
874
- referencedBy: relationships
875
- .filter((rel: any) => rel.targetTable === relTable)
876
- .map((rel: any) => rel.field)
877
- });
878
- }
879
- }
880
- }
881
-
882
- // Compile comprehensive schema information
883
- const schema = {
884
- table: {
885
- name: tableInfo.name,
886
- label: tableInfo.label,
887
- sys_id: tableInfo.sys_id,
888
- isExtendable: tableDetails.is_extendable === 'true',
889
- isSystemTable: tableDetails.sys_scope?.display_value === 'global',
890
- created: tableDetails.sys_created_on,
891
- updated: tableDetails.sys_updated_on,
892
- recordCount: tableDetails.row_count || 'Unknown',
893
- accessControls: tableDetails.access || 'Not specified'
894
- },
895
- hierarchy,
896
- fields: {
897
- total: fields.length,
898
- mandatory: fields.filter((f: any) => f.mandatory).length,
899
- references: fields.filter((f: any) => f.reference).length,
900
- calculated: fields.filter((f: any) => f.calculated).length,
901
- list: fields
902
- },
903
- relationships: {
904
- total: relationships.length,
905
- list: relationships,
906
- relatedTables
907
- },
908
- indexes: {
909
- total: indexes.length,
910
- list: indexes
911
- }
912
- };
913
-
914
- return {
915
- content: [{
916
- type: 'text',
917
- text: `šŸ” **Comprehensive Schema Discovery for ${tableInfo.label} (${tableInfo.name})**\n\n` +
918
- `šŸ“Š **Table Overview:**\n` +
919
- `- Label: ${schema.table.label}\n` +
920
- `- Name: ${schema.table.name}\n` +
921
- `- System ID: ${schema.table.sys_id}\n` +
922
- `- Extendable: ${schema.table.isExtendable ? 'Yes' : 'No'}\n` +
923
- `- System Table: ${schema.table.isSystemTable ? 'Yes' : 'No'}\n` +
924
- `- Record Count: ${schema.table.recordCount}\n\n` +
925
-
926
- (hierarchy ? `šŸ”— **Table Hierarchy:**\n` +
927
- `- Extends: ${hierarchy.extends || 'None'}\n` +
928
- `- Extended By: ${hierarchy.extendedBy?.length || 0} tables\n` +
929
- (hierarchy.extendedBy?.length > 0 ?
930
- hierarchy.extendedBy.map((t: any) => ` - ${t.label} (${t.name})`).join('\n') + '\n' : '') +
931
- '\n' : '') +
932
-
933
- `šŸ“‹ **Fields Summary:**\n` +
934
- `- Total Fields: ${schema.fields.total}\n` +
935
- `- Mandatory Fields: ${schema.fields.mandatory}\n` +
936
- `- Reference Fields: ${schema.fields.references}\n` +
937
- `- Calculated Fields: ${schema.fields.calculated}\n\n` +
938
-
939
- `šŸ”— **Relationships:**\n` +
940
- `- Total References: ${schema.relationships.total}\n` +
941
- (schema.relationships.list.length > 0 ?
942
- schema.relationships.list.map((rel: any) =>
943
- ` - ${rel.field} → ${rel.targetTable} (${rel.label})`
944
- ).join('\n') + '\n' : '') +
945
- '\n' +
946
-
947
- (indexes.length > 0 ? `šŸ”‘ **Indexes:**\n` +
948
- indexes.map((idx: any) =>
949
- `- ${idx.name} (${idx.unique ? 'Unique' : 'Non-unique'}) on: ${idx.fields}`
950
- ).join('\n') + '\n\n' : '') +
951
-
952
- `\nšŸ“ **Full Schema Details:**\n\`\`\`json\n${JSON.stringify(schema, null, 2)}\n\`\`\`\n\n` +
953
- `✨ All schema information discovered dynamically from ServiceNow!`
954
- }]
955
- };
956
- } catch (error) {
957
- this.logger.error('Failed to discover table schema:', error);
958
- throw new McpError(ErrorCode.InternalError, `Failed to discover table schema: ${error}`);
959
- }
960
- }
961
-
962
- async run() {
963
- const transport = new StdioServerTransport();
964
- await this.server.connect(transport);
965
- this.logger.info('ServiceNow Platform Development MCP Server running on stdio');
966
- }
967
- }
968
-
969
- const server = new ServiceNowPlatformDevelopmentMCP();
970
- server.run().catch(console.error);