@@ -6397,6 +6397,298 @@ window.runToolTest = runToolTest;
6397
6397
window . closeModal = closeModal ;
6398
6398
window . testGateway = testGateway ;
6399
6399
6400
+ // ===============================================
6401
+ // CONFIG EXPORT FUNCTIONALITY
6402
+ // ===============================================
6403
+
6404
+ /**
6405
+ * Global variables to store current config data
6406
+ */
6407
+ let currentConfigData = null ;
6408
+ let currentConfigType = null ;
6409
+ let currentServerName = null ;
6410
+ let currentServerId = null ;
6411
+
6412
+ /**
6413
+ * Show the config selection modal
6414
+ * @param {string } serverId - The server UUID
6415
+ * @param {string } serverName - The server name
6416
+ */
6417
+ function showConfigSelectionModal ( serverId , serverName ) {
6418
+ currentServerId = serverId ;
6419
+ currentServerName = serverName ;
6420
+
6421
+ const serverNameDisplay = safeGetElement ( "server-name-display" ) ;
6422
+ if ( serverNameDisplay ) {
6423
+ serverNameDisplay . textContent = serverName ;
6424
+ }
6425
+
6426
+ openModal ( "config-selection-modal" ) ;
6427
+ }
6428
+
6429
+ /**
6430
+ * Generate and show configuration for selected type
6431
+ * @param {string } configType - Configuration type: 'stdio', 'sse', or 'http'
6432
+ */
6433
+ async function generateAndShowConfig ( configType ) {
6434
+ try {
6435
+ console . log (
6436
+ `Generating ${ configType } config for server ${ currentServerId } ` ,
6437
+ ) ;
6438
+
6439
+ // First, fetch the server details
6440
+ const response = await fetchWithTimeout (
6441
+ `${ window . ROOT_PATH } /admin/servers/${ currentServerId } ` ,
6442
+ ) ;
6443
+
6444
+ if ( ! response . ok ) {
6445
+ throw new Error ( `HTTP ${ response . status } : ${ response . statusText } ` ) ;
6446
+ }
6447
+
6448
+ const server = await response . json ( ) ;
6449
+
6450
+ // Generate the configuration
6451
+ const config = generateConfig ( server , configType ) ;
6452
+
6453
+ // Store data for modal
6454
+ currentConfigData = config ;
6455
+ currentConfigType = configType ;
6456
+
6457
+ // Close selection modal and show config display modal
6458
+ closeModal ( "config-selection-modal" ) ;
6459
+ showConfigDisplayModal ( server , configType , config ) ;
6460
+
6461
+ console . log ( "✓ Config generated successfully" ) ;
6462
+ } catch ( error ) {
6463
+ console . error ( "Error generating config:" , error ) ;
6464
+ const errorMessage = handleFetchError ( error , "generate configuration" ) ;
6465
+ showErrorMessage ( errorMessage ) ;
6466
+ }
6467
+ }
6468
+
6469
+ /**
6470
+ * Export server configuration in specified format
6471
+ * @param {string } serverId - The server UUID
6472
+ * @param {string } configType - Configuration type: 'stdio', 'sse', or 'http'
6473
+ */
6474
+ async function exportServerConfig ( serverId , configType ) {
6475
+ try {
6476
+ console . log ( `Exporting ${ configType } config for server ${ serverId } ` ) ;
6477
+
6478
+ // First, fetch the server details
6479
+ const response = await fetchWithTimeout (
6480
+ `${ window . ROOT_PATH } /admin/servers/${ serverId } ` ,
6481
+ ) ;
6482
+
6483
+ if ( ! response . ok ) {
6484
+ throw new Error ( `HTTP ${ response . status } : ${ response . statusText } ` ) ;
6485
+ }
6486
+
6487
+ const server = await response . json ( ) ;
6488
+
6489
+ // Generate the configuration
6490
+ const config = generateConfig ( server , configType ) ;
6491
+
6492
+ // Store data for modal
6493
+ currentConfigData = config ;
6494
+ currentConfigType = configType ;
6495
+ currentServerName = server . name ;
6496
+
6497
+ // Show the modal with the config
6498
+ showConfigDisplayModal ( server , configType , config ) ;
6499
+
6500
+ console . log ( "✓ Config generated successfully" ) ;
6501
+ } catch ( error ) {
6502
+ console . error ( "Error generating config:" , error ) ;
6503
+ const errorMessage = handleFetchError ( error , "generate configuration" ) ;
6504
+ showErrorMessage ( errorMessage ) ;
6505
+ }
6506
+ }
6507
+
6508
+ /**
6509
+ * Generate configuration object based on server and type
6510
+ * @param {Object } server - Server object from API
6511
+ * @param {string } configType - Configuration type
6512
+ * @returns {Object } - Generated configuration object
6513
+ */
6514
+ function generateConfig ( server , configType ) {
6515
+ const currentHost = window . location . hostname ;
6516
+ const currentPort =
6517
+ window . location . port ||
6518
+ ( window . location . protocol === "https:" ? "443" : "80" ) ;
6519
+ const protocol = window . location . protocol ;
6520
+ const baseUrl = `${ protocol } //${ currentHost } ${ currentPort !== "80" && currentPort !== "443" ? ":" + currentPort : "" } ` ;
6521
+
6522
+ // Clean server name for use as config key (alphanumeric and hyphens only)
6523
+ const cleanServerName = server . name
6524
+ . toLowerCase ( )
6525
+ . replace ( / [ ^ a - z 0 - 9 - ] / g, "-" )
6526
+ . replace ( / - + / g, "-" )
6527
+ . replace ( / ^ - | - $ / g, "" ) ;
6528
+
6529
+ switch ( configType ) {
6530
+ case "stdio" :
6531
+ return {
6532
+ mcpServers : {
6533
+ [ cleanServerName ] : {
6534
+ command : "python" ,
6535
+ args : [ "-m" , "mcpgateway.wrapper" ] ,
6536
+ env : {
6537
+ MCP_AUTH_TOKEN : "your-token-here" ,
6538
+ MCP_SERVER_CATALOG_URLS : `${ baseUrl } /servers/${ server . id } ` ,
6539
+ MCP_TOOL_CALL_TIMEOUT : "120" ,
6540
+ } ,
6541
+ } ,
6542
+ } ,
6543
+ } ;
6544
+
6545
+ case "sse" :
6546
+ return {
6547
+ mcpServers : {
6548
+ [ cleanServerName ] : {
6549
+ type : "sse" ,
6550
+ url : `${ baseUrl } /servers/${ server . id } /sse` ,
6551
+ headers : {
6552
+ Authorization : "Bearer your-token-here" ,
6553
+ } ,
6554
+ } ,
6555
+ } ,
6556
+ } ;
6557
+
6558
+ case "http" :
6559
+ return {
6560
+ mcpServers : {
6561
+ [ cleanServerName ] : {
6562
+ type : "http" ,
6563
+ url : `${ baseUrl } /servers/${ server . id } ` ,
6564
+ headers : {
6565
+ Authorization : "Bearer your-token-here" ,
6566
+ } ,
6567
+ } ,
6568
+ } ,
6569
+ } ;
6570
+
6571
+ default :
6572
+ throw new Error ( `Unknown config type: ${ configType } ` ) ;
6573
+ }
6574
+ }
6575
+
6576
+ /**
6577
+ * Show the config display modal with generated configuration
6578
+ * @param {Object } server - Server object
6579
+ * @param {string } configType - Configuration type
6580
+ * @param {Object } config - Generated configuration
6581
+ */
6582
+ function showConfigDisplayModal ( server , configType , config ) {
6583
+ const descriptions = {
6584
+ stdio : "Configuration for Claude Desktop, CLI tools, and stdio-based MCP clients" ,
6585
+ sse : "Configuration for LangChain, LlamaIndex, and other SSE-based frameworks" ,
6586
+ http : "Configuration for REST clients and HTTP-based MCP integrations" ,
6587
+ } ;
6588
+
6589
+ const usageInstructions = {
6590
+ stdio : "Save as .mcp.json in your user directory or use in Claude Desktop settings" ,
6591
+ sse : "Use with MCP client libraries that support Server-Sent Events transport" ,
6592
+ http : "Use with HTTP clients or REST API wrappers for MCP protocol" ,
6593
+ } ;
6594
+
6595
+ // Update modal content
6596
+ const descriptionEl = safeGetElement ( "config-description" ) ;
6597
+ const usageEl = safeGetElement ( "config-usage" ) ;
6598
+ const contentEl = safeGetElement ( "config-content" ) ;
6599
+
6600
+ if ( descriptionEl ) {
6601
+ descriptionEl . textContent = `${ descriptions [ configType ] } for server "${ server . name } "` ;
6602
+ }
6603
+
6604
+ if ( usageEl ) {
6605
+ usageEl . textContent = usageInstructions [ configType ] ;
6606
+ }
6607
+
6608
+ if ( contentEl ) {
6609
+ contentEl . value = JSON . stringify ( config , null , 2 ) ;
6610
+ }
6611
+
6612
+ // Update title and open the modal
6613
+ const titleEl = safeGetElement ( "config-display-title" ) ;
6614
+ if ( titleEl ) {
6615
+ titleEl . textContent = `${ configType . toUpperCase ( ) } Configuration for ${ server . name } ` ;
6616
+ }
6617
+ openModal ( "config-display-modal" ) ;
6618
+ }
6619
+
6620
+ /**
6621
+ * Copy configuration to clipboard
6622
+ */
6623
+ async function copyConfigToClipboard ( ) {
6624
+ try {
6625
+ const contentEl = safeGetElement ( "config-content" ) ;
6626
+ if ( ! contentEl ) {
6627
+ throw new Error ( "Config content not found" ) ;
6628
+ }
6629
+
6630
+ await navigator . clipboard . writeText ( contentEl . value ) ;
6631
+ showSuccessMessage ( "Configuration copied to clipboard!" ) ;
6632
+ } catch ( error ) {
6633
+ console . error ( "Error copying to clipboard:" , error ) ;
6634
+
6635
+ // Fallback: select the text for manual copying
6636
+ const contentEl = safeGetElement ( "config-content" ) ;
6637
+ if ( contentEl ) {
6638
+ contentEl . select ( ) ;
6639
+ contentEl . setSelectionRange ( 0 , 99999 ) ; // For mobile devices
6640
+ showErrorMessage ( "Please copy the selected text manually (Ctrl+C)" ) ;
6641
+ } else {
6642
+ showErrorMessage ( "Failed to copy configuration" ) ;
6643
+ }
6644
+ }
6645
+ }
6646
+
6647
+ /**
6648
+ * Download configuration as JSON file
6649
+ */
6650
+ function downloadConfig ( ) {
6651
+ if ( ! currentConfigData || ! currentConfigType || ! currentServerName ) {
6652
+ showErrorMessage ( "No configuration data available" ) ;
6653
+ return ;
6654
+ }
6655
+
6656
+ try {
6657
+ const content = JSON . stringify ( currentConfigData , null , 2 ) ;
6658
+ const blob = new Blob ( [ content ] , { type : "application/json" } ) ;
6659
+ const url = window . URL . createObjectURL ( blob ) ;
6660
+
6661
+ const a = document . createElement ( "a" ) ;
6662
+ a . href = url ;
6663
+ a . download = `${ currentServerName } -${ currentConfigType } -config.json` ;
6664
+ document . body . appendChild ( a ) ;
6665
+ a . click ( ) ;
6666
+ document . body . removeChild ( a ) ;
6667
+ window . URL . revokeObjectURL ( url ) ;
6668
+
6669
+ showSuccessMessage ( `Configuration downloaded as ${ a . download } ` ) ;
6670
+ } catch ( error ) {
6671
+ console . error ( "Error downloading config:" , error ) ;
6672
+ showErrorMessage ( "Failed to download configuration" ) ;
6673
+ }
6674
+ }
6675
+
6676
+ /**
6677
+ * Go back to config selection modal
6678
+ */
6679
+ function goBackToSelection ( ) {
6680
+ closeModal ( "config-display-modal" ) ;
6681
+ openModal ( "config-selection-modal" ) ;
6682
+ }
6683
+
6684
+ // Export functions to global scope immediately after definition
6685
+ window . showConfigSelectionModal = showConfigSelectionModal ;
6686
+ window . generateAndShowConfig = generateAndShowConfig ;
6687
+ window . exportServerConfig = exportServerConfig ;
6688
+ window . copyConfigToClipboard = copyConfigToClipboard ;
6689
+ window . downloadConfig = downloadConfig ;
6690
+ window . goBackToSelection = goBackToSelection ;
6691
+
6400
6692
// ===============================================
6401
6693
// TAG FILTERING FUNCTIONALITY
6402
6694
// ===============================================
0 commit comments