snow-flow 1.3.28 → 1.3.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,422 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Deployment Metadata Handler
5
+ *
6
+ * Solves Issue #3: Metadata Response Failures
7
+ * Ensures all deployments return proper sys_id and API endpoints
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.DeploymentMetadataHandler = void 0;
11
+ exports.getMetadataHandler = getMetadataHandler;
12
+ exports.ensureDeploymentMetadata = ensureDeploymentMetadata;
13
+ const servicenow_client_js_1 = require("./servicenow-client.js");
14
+ const snow_oauth_js_1 = require("./snow-oauth.js");
15
+ const logger_js_1 = require("./logger.js");
16
+ class DeploymentMetadataHandler {
17
+ constructor() {
18
+ this.metadataCache = new Map();
19
+ this.client = new servicenow_client_js_1.ServiceNowClient();
20
+ this.oauth = new snow_oauth_js_1.ServiceNowOAuth();
21
+ this.logger = new logger_js_1.Logger('DeploymentMetadataHandler');
22
+ }
23
+ /**
24
+ * Extract metadata from deployment response
25
+ */
26
+ async extractMetadata(deploymentType, deploymentResponse, additionalInfo) {
27
+ try {
28
+ let metadata = null;
29
+ switch (deploymentType) {
30
+ case 'flow':
31
+ metadata = await this.extractFlowMetadata(deploymentResponse, additionalInfo);
32
+ break;
33
+ case 'widget':
34
+ metadata = await this.extractWidgetMetadata(deploymentResponse, additionalInfo);
35
+ break;
36
+ case 'script':
37
+ metadata = await this.extractScriptMetadata(deploymentResponse, additionalInfo);
38
+ break;
39
+ case 'business_rule':
40
+ metadata = await this.extractBusinessRuleMetadata(deploymentResponse, additionalInfo);
41
+ break;
42
+ default:
43
+ metadata = await this.extractGenericMetadata(deploymentType, deploymentResponse, additionalInfo);
44
+ }
45
+ if (!metadata) {
46
+ throw new Error('Failed to extract metadata from deployment response');
47
+ }
48
+ // Verify the deployment
49
+ const verification = await this.verifyDeployment(metadata);
50
+ metadata.verification_status = verification.exists && verification.accessible ? 'verified' : 'failed';
51
+ // Cache the metadata
52
+ this.metadataCache.set(metadata.sys_id, metadata);
53
+ return {
54
+ success: true,
55
+ metadata,
56
+ verification
57
+ };
58
+ }
59
+ catch (error) {
60
+ this.logger.error('Metadata extraction failed:', error);
61
+ return {
62
+ success: false,
63
+ error: error instanceof Error ? error.message : String(error)
64
+ };
65
+ }
66
+ }
67
+ /**
68
+ * Extract flow metadata
69
+ */
70
+ async extractFlowMetadata(response, additionalInfo) {
71
+ let sysId = null;
72
+ let name = '';
73
+ // Try multiple paths to find sys_id
74
+ sysId = response?.sys_id ||
75
+ response?.result?.sys_id ||
76
+ response?.flow?.sys_id ||
77
+ additionalInfo?.flowSysId ||
78
+ additionalInfo?.sys_id;
79
+ // If still no sys_id, try to find it from update set
80
+ if (!sysId && additionalInfo?.update_set_id) {
81
+ sysId = await this.findFlowFromUpdateSet(additionalInfo.update_set_id);
82
+ }
83
+ // If still no sys_id, search by name
84
+ if (!sysId && (response?.name || additionalInfo?.name)) {
85
+ name = response?.name || additionalInfo?.name;
86
+ sysId = await this.findFlowByName(name);
87
+ }
88
+ if (!sysId) {
89
+ this.logger.warn('Could not find flow sys_id in response');
90
+ return null;
91
+ }
92
+ // Get additional details
93
+ const flowDetails = await this.getFlowDetails(sysId);
94
+ const credentials = await this.oauth.getCredentials();
95
+ return {
96
+ sys_id: sysId,
97
+ name: flowDetails?.name || name || 'Unknown Flow',
98
+ type: 'flow',
99
+ table: 'sys_hub_flow',
100
+ api_endpoint: `https://${credentials?.instance}/api/now/table/sys_hub_flow/${sysId}`,
101
+ ui_url: `https://${credentials?.instance}/flow-designer/${sysId}`,
102
+ created_on: flowDetails?.sys_created_on,
103
+ created_by: flowDetails?.sys_created_by,
104
+ update_set_id: additionalInfo?.update_set_id
105
+ };
106
+ }
107
+ /**
108
+ * Extract widget metadata
109
+ */
110
+ async extractWidgetMetadata(response, additionalInfo) {
111
+ let sysId = null;
112
+ let name = '';
113
+ // Try multiple paths to find sys_id
114
+ sysId = response?.sys_id ||
115
+ response?.result?.sys_id ||
116
+ response?.widget?.sys_id ||
117
+ additionalInfo?.widgetSysId ||
118
+ additionalInfo?.sys_id;
119
+ // Search by name if needed
120
+ if (!sysId && (response?.name || additionalInfo?.name)) {
121
+ name = response?.name || additionalInfo?.name;
122
+ sysId = await this.findWidgetByName(name);
123
+ }
124
+ if (!sysId) {
125
+ this.logger.warn('Could not find widget sys_id in response');
126
+ return null;
127
+ }
128
+ const credentials = await this.oauth.getCredentials();
129
+ return {
130
+ sys_id: sysId,
131
+ name: name || response?.title || 'Unknown Widget',
132
+ type: 'widget',
133
+ table: 'sp_widget',
134
+ api_endpoint: `https://${credentials?.instance}/api/now/table/sp_widget/${sysId}`,
135
+ ui_url: `https://${credentials?.instance}/sp_config?id=widget_editor&sys_id=${sysId}`,
136
+ update_set_id: additionalInfo?.update_set_id
137
+ };
138
+ }
139
+ /**
140
+ * Extract script include metadata
141
+ */
142
+ async extractScriptMetadata(response, additionalInfo) {
143
+ let sysId = null;
144
+ sysId = response?.sys_id ||
145
+ response?.result?.sys_id ||
146
+ additionalInfo?.sys_id;
147
+ if (!sysId && response?.name) {
148
+ sysId = await this.findScriptIncludeByName(response.name);
149
+ }
150
+ if (!sysId)
151
+ return null;
152
+ const credentials = await this.oauth.getCredentials();
153
+ return {
154
+ sys_id: sysId,
155
+ name: response?.name || 'Unknown Script',
156
+ type: 'script_include',
157
+ table: 'sys_script_include',
158
+ api_endpoint: `https://${credentials?.instance}/api/now/table/sys_script_include/${sysId}`,
159
+ ui_url: `https://${credentials?.instance}/sys_script_include.do?sys_id=${sysId}`
160
+ };
161
+ }
162
+ /**
163
+ * Extract business rule metadata
164
+ */
165
+ async extractBusinessRuleMetadata(response, additionalInfo) {
166
+ let sysId = null;
167
+ sysId = response?.sys_id ||
168
+ response?.result?.sys_id ||
169
+ additionalInfo?.sys_id;
170
+ if (!sysId && response?.name) {
171
+ sysId = await this.findBusinessRuleByName(response.name, response?.table);
172
+ }
173
+ if (!sysId)
174
+ return null;
175
+ const credentials = await this.oauth.getCredentials();
176
+ return {
177
+ sys_id: sysId,
178
+ name: response?.name || 'Unknown Business Rule',
179
+ type: 'business_rule',
180
+ table: 'sys_script',
181
+ api_endpoint: `https://${credentials?.instance}/api/now/table/sys_script/${sysId}`,
182
+ ui_url: `https://${credentials?.instance}/sys_script.do?sys_id=${sysId}`
183
+ };
184
+ }
185
+ /**
186
+ * Extract generic metadata
187
+ */
188
+ async extractGenericMetadata(type, response, additionalInfo) {
189
+ const sysId = response?.sys_id || response?.result?.sys_id || additionalInfo?.sys_id;
190
+ if (!sysId)
191
+ return null;
192
+ const credentials = await this.oauth.getCredentials();
193
+ const table = additionalInfo?.table || this.getTableForType(type);
194
+ return {
195
+ sys_id: sysId,
196
+ name: response?.name || additionalInfo?.name || `Unknown ${type}`,
197
+ type,
198
+ table,
199
+ api_endpoint: `https://${credentials?.instance}/api/now/table/${table}/${sysId}`,
200
+ ui_url: `https://${credentials?.instance}/${table}.do?sys_id=${sysId}`
201
+ };
202
+ }
203
+ /**
204
+ * Find flow from update set
205
+ */
206
+ async findFlowFromUpdateSet(updateSetId) {
207
+ try {
208
+ const response = await this.client.makeRequest({
209
+ method: 'GET',
210
+ url: '/api/now/table/sys_update_xml',
211
+ params: {
212
+ sysparm_query: `update_set=${updateSetId}^name^STARTSWITHsys_hub_flow_`,
213
+ sysparm_limit: 1,
214
+ sysparm_fields: 'name'
215
+ }
216
+ });
217
+ if (response.result && response.result.length > 0) {
218
+ return response.result[0].name.replace('sys_hub_flow_', '');
219
+ }
220
+ }
221
+ catch (error) {
222
+ this.logger.warn('Error finding flow from update set:', error);
223
+ }
224
+ return null;
225
+ }
226
+ /**
227
+ * Find flow by name
228
+ */
229
+ async findFlowByName(name) {
230
+ try {
231
+ const response = await this.client.makeRequest({
232
+ method: 'GET',
233
+ url: '/api/now/table/sys_hub_flow',
234
+ params: {
235
+ sysparm_query: `name=${name}^ORinternal_name=${name}`,
236
+ sysparm_limit: 1,
237
+ sysparm_fields: 'sys_id'
238
+ }
239
+ });
240
+ if (response.result && response.result.length > 0) {
241
+ return response.result[0].sys_id;
242
+ }
243
+ }
244
+ catch (error) {
245
+ this.logger.warn('Error finding flow by name:', error);
246
+ }
247
+ return null;
248
+ }
249
+ /**
250
+ * Find widget by name
251
+ */
252
+ async findWidgetByName(name) {
253
+ try {
254
+ const response = await this.client.makeRequest({
255
+ method: 'GET',
256
+ url: '/api/now/table/sp_widget',
257
+ params: {
258
+ sysparm_query: `name=${name}^ORid=${name}`,
259
+ sysparm_limit: 1,
260
+ sysparm_fields: 'sys_id'
261
+ }
262
+ });
263
+ if (response.result && response.result.length > 0) {
264
+ return response.result[0].sys_id;
265
+ }
266
+ }
267
+ catch (error) {
268
+ this.logger.warn('Error finding widget by name:', error);
269
+ }
270
+ return null;
271
+ }
272
+ /**
273
+ * Find script include by name
274
+ */
275
+ async findScriptIncludeByName(name) {
276
+ try {
277
+ const response = await this.client.makeRequest({
278
+ method: 'GET',
279
+ url: '/api/now/table/sys_script_include',
280
+ params: {
281
+ sysparm_query: `name=${name}^ORapi_name=${name}`,
282
+ sysparm_limit: 1,
283
+ sysparm_fields: 'sys_id'
284
+ }
285
+ });
286
+ if (response.result && response.result.length > 0) {
287
+ return response.result[0].sys_id;
288
+ }
289
+ }
290
+ catch (error) {
291
+ this.logger.warn('Error finding script include by name:', error);
292
+ }
293
+ return null;
294
+ }
295
+ /**
296
+ * Find business rule by name
297
+ */
298
+ async findBusinessRuleByName(name, table) {
299
+ try {
300
+ let query = `name=${name}`;
301
+ if (table) {
302
+ query += `^collection=${table}`;
303
+ }
304
+ const response = await this.client.makeRequest({
305
+ method: 'GET',
306
+ url: '/api/now/table/sys_script',
307
+ params: {
308
+ sysparm_query: query,
309
+ sysparm_limit: 1,
310
+ sysparm_fields: 'sys_id'
311
+ }
312
+ });
313
+ if (response.result && response.result.length > 0) {
314
+ return response.result[0].sys_id;
315
+ }
316
+ }
317
+ catch (error) {
318
+ this.logger.warn('Error finding business rule by name:', error);
319
+ }
320
+ return null;
321
+ }
322
+ /**
323
+ * Get flow details
324
+ */
325
+ async getFlowDetails(sysId) {
326
+ try {
327
+ const response = await this.client.makeRequest({
328
+ method: 'GET',
329
+ url: `/api/now/table/sys_hub_flow/${sysId}`,
330
+ params: {
331
+ sysparm_fields: 'name,sys_created_on,sys_created_by,internal_name'
332
+ }
333
+ });
334
+ return response.result;
335
+ }
336
+ catch (error) {
337
+ this.logger.warn('Error getting flow details:', error);
338
+ return null;
339
+ }
340
+ }
341
+ /**
342
+ * Verify deployment exists and is accessible
343
+ */
344
+ async verifyDeployment(metadata) {
345
+ const verification = {
346
+ exists: false,
347
+ accessible: false,
348
+ functional: false
349
+ };
350
+ try {
351
+ // Check if record exists
352
+ const response = await this.client.makeRequest({
353
+ method: 'GET',
354
+ url: `/api/now/table/${metadata.table}/${metadata.sys_id}`,
355
+ params: {
356
+ sysparm_fields: 'sys_id,name'
357
+ }
358
+ });
359
+ verification.exists = !!response.result;
360
+ verification.accessible = response.success;
361
+ // For flows, check if it's active
362
+ if (metadata.type === 'flow' && response.result) {
363
+ verification.functional = response.result.active === 'true' || response.result.active === true;
364
+ }
365
+ else {
366
+ verification.functional = verification.exists;
367
+ }
368
+ }
369
+ catch (error) {
370
+ this.logger.warn('Verification failed:', error);
371
+ }
372
+ return verification;
373
+ }
374
+ /**
375
+ * Get table name for deployment type
376
+ */
377
+ getTableForType(type) {
378
+ const tableMap = {
379
+ 'flow': 'sys_hub_flow',
380
+ 'widget': 'sp_widget',
381
+ 'script_include': 'sys_script_include',
382
+ 'business_rule': 'sys_script',
383
+ 'ui_script': 'sys_ui_script',
384
+ 'client_script': 'sys_script_client',
385
+ 'table': 'sys_db_object',
386
+ 'application': 'sys_app'
387
+ };
388
+ return tableMap[type] || 'sys_metadata';
389
+ }
390
+ /**
391
+ * Get cached metadata
392
+ */
393
+ getCachedMetadata(sysId) {
394
+ return this.metadataCache.get(sysId) || null;
395
+ }
396
+ /**
397
+ * Clear metadata cache
398
+ */
399
+ clearCache() {
400
+ this.metadataCache.clear();
401
+ }
402
+ }
403
+ exports.DeploymentMetadataHandler = DeploymentMetadataHandler;
404
+ // Singleton instance
405
+ let handlerInstance = null;
406
+ /**
407
+ * Get or create handler instance
408
+ */
409
+ function getMetadataHandler() {
410
+ if (!handlerInstance) {
411
+ handlerInstance = new DeploymentMetadataHandler();
412
+ }
413
+ return handlerInstance;
414
+ }
415
+ /**
416
+ * Helper to ensure deployment returns metadata
417
+ */
418
+ async function ensureDeploymentMetadata(deploymentType, deploymentResponse, additionalInfo) {
419
+ const handler = getMetadataHandler();
420
+ return handler.extractMetadata(deploymentType, deploymentResponse, additionalInfo);
421
+ }
422
+ exports.default = DeploymentMetadataHandler;
@@ -0,0 +1,271 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * MCP Tool Registry Mapper
5
+ *
6
+ * Solves Issue #2: Tool Registry Mapping Failures
7
+ * Provides robust tool name resolution between different MCP providers
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MCPToolRegistry = void 0;
11
+ exports.getToolRegistry = getToolRegistry;
12
+ exports.resolveToolName = resolveToolName;
13
+ exports.isValidTool = isValidTool;
14
+ exports.suggestTools = suggestTools;
15
+ const logger_js_1 = require("./logger.js");
16
+ class MCPToolRegistry {
17
+ constructor() {
18
+ this.toolMappings = new Map();
19
+ this.logger = new logger_js_1.Logger('MCPToolRegistry');
20
+ this.initializeDefaultMappings();
21
+ }
22
+ /**
23
+ * Initialize default tool mappings
24
+ */
25
+ initializeDefaultMappings() {
26
+ // ServiceNow table schema discovery - common confusion point
27
+ this.registerTool({
28
+ canonicalName: 'table_schema_discovery',
29
+ aliases: [
30
+ 'mcp__servicenow-operations__snow_table_schema_discovery',
31
+ 'snow_table_schema_discovery',
32
+ 'table_schema',
33
+ 'schema_discovery'
34
+ ],
35
+ provider: 'servicenow-platform-development',
36
+ actualTool: 'mcp__servicenow-platform-development__snow_table_schema_discovery',
37
+ description: 'Comprehensive table schema discovery'
38
+ });
39
+ // Flow deployment tools
40
+ this.registerTool({
41
+ canonicalName: 'deploy_flow',
42
+ aliases: [
43
+ 'mcp__servicenow-deployment__snow_deploy_flow',
44
+ 'snow_deploy_flow',
45
+ 'deploy_flow',
46
+ 'flow_deploy'
47
+ ],
48
+ provider: 'servicenow-deployment',
49
+ actualTool: 'mcp__servicenow-deployment__snow_deploy',
50
+ description: 'Deploy flows to ServiceNow'
51
+ });
52
+ // Widget deployment
53
+ this.registerTool({
54
+ canonicalName: 'deploy_widget',
55
+ aliases: [
56
+ 'mcp__servicenow-deployment__snow_deploy_widget',
57
+ 'snow_deploy_widget',
58
+ 'deploy_widget',
59
+ 'widget_deploy'
60
+ ],
61
+ provider: 'servicenow-deployment',
62
+ actualTool: 'mcp__servicenow-deployment__snow_deploy',
63
+ description: 'Deploy widgets to ServiceNow'
64
+ });
65
+ // Flow creation
66
+ this.registerTool({
67
+ canonicalName: 'create_flow',
68
+ aliases: [
69
+ 'mcp__servicenow-flow-composer__snow_create_flow',
70
+ 'snow_create_flow',
71
+ 'create_flow',
72
+ 'flow_create',
73
+ 'snow_xml_flow_from_instruction'
74
+ ],
75
+ provider: 'servicenow-flow-composer',
76
+ actualTool: 'mcp__servicenow-flow-composer__snow_create_flow',
77
+ description: 'Create flows from natural language'
78
+ });
79
+ // Update Set management
80
+ this.registerTool({
81
+ canonicalName: 'update_set_create',
82
+ aliases: [
83
+ 'mcp__servicenow-update-set__snow_update_set_create',
84
+ 'snow_update_set_create',
85
+ 'create_update_set',
86
+ 'update_set_new'
87
+ ],
88
+ provider: 'servicenow-update-set',
89
+ actualTool: 'mcp__servicenow-update-set__snow_update_set_create',
90
+ description: 'Create Update Sets'
91
+ });
92
+ // Authentication diagnostics
93
+ this.registerTool({
94
+ canonicalName: 'auth_diagnostics',
95
+ aliases: [
96
+ 'mcp__servicenow-deployment__snow_auth_diagnostics',
97
+ 'snow_auth_diagnostics',
98
+ 'auth_check',
99
+ 'permission_check'
100
+ ],
101
+ provider: 'servicenow-deployment',
102
+ actualTool: 'mcp__servicenow-deployment__snow_auth_diagnostics',
103
+ description: 'Authentication and permission diagnostics'
104
+ });
105
+ // Catalog item management
106
+ this.registerTool({
107
+ canonicalName: 'catalog_item_manager',
108
+ aliases: [
109
+ 'mcp__servicenow-operations__snow_catalog_item_manager',
110
+ 'snow_catalog_item_manager',
111
+ 'catalog_manager',
112
+ 'manage_catalog'
113
+ ],
114
+ provider: 'servicenow-operations',
115
+ actualTool: 'mcp__servicenow-operations__snow_catalog_item_manager',
116
+ description: 'Manage service catalog items'
117
+ });
118
+ // Platform development tools
119
+ this.registerTool({
120
+ canonicalName: 'discover_table_fields',
121
+ aliases: [
122
+ 'mcp__servicenow-platform-development__snow_discover_table_fields',
123
+ 'snow_discover_table_fields',
124
+ 'discover_fields',
125
+ 'table_fields'
126
+ ],
127
+ provider: 'servicenow-platform-development',
128
+ actualTool: 'mcp__servicenow-platform-development__snow_discover_table_fields',
129
+ description: 'Discover table fields'
130
+ });
131
+ // Add more mappings as needed...
132
+ }
133
+ /**
134
+ * Register a tool mapping
135
+ */
136
+ registerTool(mapping) {
137
+ // Register by canonical name
138
+ this.toolMappings.set(mapping.canonicalName, mapping);
139
+ // Register by actual tool name
140
+ this.toolMappings.set(mapping.actualTool, mapping);
141
+ // Register by all aliases
142
+ mapping.aliases.forEach(alias => {
143
+ this.toolMappings.set(alias.toLowerCase(), mapping);
144
+ });
145
+ this.logger.debug(`Registered tool: ${mapping.canonicalName} with ${mapping.aliases.length} aliases`);
146
+ }
147
+ /**
148
+ * Resolve a tool name to its actual MCP tool
149
+ */
150
+ resolveTool(toolName) {
151
+ // Try exact match first
152
+ let mapping = this.toolMappings.get(toolName);
153
+ // Try lowercase match
154
+ if (!mapping) {
155
+ mapping = this.toolMappings.get(toolName.toLowerCase());
156
+ }
157
+ // Try partial matches
158
+ if (!mapping) {
159
+ const searchKey = toolName.toLowerCase();
160
+ for (const [key, value] of this.toolMappings.entries()) {
161
+ if (key.includes(searchKey) || searchKey.includes(key)) {
162
+ mapping = value;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ if (mapping) {
168
+ this.logger.debug(`Resolved '${toolName}' to '${mapping.actualTool}'`);
169
+ return mapping.actualTool;
170
+ }
171
+ this.logger.warn(`Could not resolve tool: ${toolName}`);
172
+ return null;
173
+ }
174
+ /**
175
+ * Get all tools for a provider
176
+ */
177
+ getProviderTools(provider) {
178
+ const tools = [];
179
+ const seen = new Set();
180
+ for (const mapping of this.toolMappings.values()) {
181
+ if (mapping.provider === provider && !seen.has(mapping.canonicalName)) {
182
+ tools.push(mapping);
183
+ seen.add(mapping.canonicalName);
184
+ }
185
+ }
186
+ return tools;
187
+ }
188
+ /**
189
+ * Search tools by keyword
190
+ */
191
+ searchTools(keyword) {
192
+ const results = [];
193
+ const seen = new Set();
194
+ const searchKey = keyword.toLowerCase();
195
+ for (const mapping of this.toolMappings.values()) {
196
+ if (seen.has(mapping.canonicalName))
197
+ continue;
198
+ if (mapping.canonicalName.includes(searchKey) ||
199
+ mapping.description?.toLowerCase().includes(searchKey) ||
200
+ mapping.aliases.some(alias => alias.toLowerCase().includes(searchKey))) {
201
+ results.push(mapping);
202
+ seen.add(mapping.canonicalName);
203
+ }
204
+ }
205
+ return results;
206
+ }
207
+ /**
208
+ * Check if a tool exists
209
+ */
210
+ toolExists(toolName) {
211
+ return this.resolveTool(toolName) !== null;
212
+ }
213
+ /**
214
+ * Get tool info
215
+ */
216
+ getToolInfo(toolName) {
217
+ const resolved = this.resolveTool(toolName);
218
+ if (!resolved)
219
+ return null;
220
+ return this.toolMappings.get(resolved) || null;
221
+ }
222
+ /**
223
+ * Export all mappings for documentation
224
+ */
225
+ exportMappings() {
226
+ const exports = {};
227
+ const seen = new Set();
228
+ for (const mapping of this.toolMappings.values()) {
229
+ if (!seen.has(mapping.canonicalName)) {
230
+ exports[mapping.canonicalName] = mapping;
231
+ seen.add(mapping.canonicalName);
232
+ }
233
+ }
234
+ return exports;
235
+ }
236
+ }
237
+ exports.MCPToolRegistry = MCPToolRegistry;
238
+ // Singleton instance
239
+ let registryInstance = null;
240
+ /**
241
+ * Get or create registry instance
242
+ */
243
+ function getToolRegistry() {
244
+ if (!registryInstance) {
245
+ registryInstance = new MCPToolRegistry();
246
+ }
247
+ return registryInstance;
248
+ }
249
+ /**
250
+ * Helper function to resolve tool names
251
+ */
252
+ function resolveToolName(toolName) {
253
+ const registry = getToolRegistry();
254
+ return registry.resolveTool(toolName) || toolName;
255
+ }
256
+ /**
257
+ * Helper to check if tool exists
258
+ */
259
+ function isValidTool(toolName) {
260
+ const registry = getToolRegistry();
261
+ return registry.toolExists(toolName);
262
+ }
263
+ /**
264
+ * Helper to get tool suggestions
265
+ */
266
+ function suggestTools(partial) {
267
+ const registry = getToolRegistry();
268
+ return registry.searchTools(partial);
269
+ }
270
+ // Export types and default instance
271
+ exports.default = MCPToolRegistry;