@aws/lsp-codewhisperer 0.0.69 → 0.0.71

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 (137) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/out/language-server/agenticChat/agenticChatController.js +53 -28
  3. package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
  4. package/out/language-server/agenticChat/constants/constants.d.ts +1 -1
  5. package/out/language-server/agenticChat/constants/constants.js +2 -1
  6. package/out/language-server/agenticChat/constants/constants.js.map +1 -1
  7. package/out/language-server/agenticChat/constants/toolConstants.d.ts +1 -1
  8. package/out/language-server/agenticChat/constants/toolConstants.js +2 -2
  9. package/out/language-server/agenticChat/constants/toolConstants.js.map +1 -1
  10. package/out/language-server/agenticChat/context/agenticChatTriggerContext.js +1 -1
  11. package/out/language-server/agenticChat/context/agenticChatTriggerContext.js.map +1 -1
  12. package/out/language-server/agenticChat/qAgenticChatServer.d.ts +1 -1
  13. package/out/language-server/agenticChat/qAgenticChatServer.js +7 -8
  14. package/out/language-server/agenticChat/qAgenticChatServer.js.map +1 -1
  15. package/out/language-server/agenticChat/tools/chatDb/chatDb.d.ts +1 -0
  16. package/out/language-server/agenticChat/tools/chatDb/chatDb.js +3 -3
  17. package/out/language-server/agenticChat/tools/chatDb/chatDb.js.map +1 -1
  18. package/out/language-server/agenticChat/tools/executeBash.d.ts +3 -1
  19. package/out/language-server/agenticChat/tools/executeBash.js +28 -24
  20. package/out/language-server/agenticChat/tools/executeBash.js.map +1 -1
  21. package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js +258 -165
  22. package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js.map +1 -1
  23. package/out/language-server/agenticChat/tools/mcp/mcpManager.d.ts +42 -17
  24. package/out/language-server/agenticChat/tools/mcp/mcpManager.js +254 -78
  25. package/out/language-server/agenticChat/tools/mcp/mcpManager.js.map +1 -1
  26. package/out/language-server/agenticChat/tools/mcp/mcpTypes.d.ts +3 -1
  27. package/out/language-server/agenticChat/tools/mcp/mcpTypes.js.map +1 -1
  28. package/out/language-server/agenticChat/tools/mcp/mcpUtils.js +36 -16
  29. package/out/language-server/agenticChat/tools/mcp/mcpUtils.js.map +1 -1
  30. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReview.d.ts → codeReview.d.ts} +4 -3
  31. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReview.js → codeReview.js} +179 -127
  32. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js.map +1 -0
  33. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewConstants.d.ts → codeReviewConstants.d.ts} +8 -6
  34. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewConstants.js → codeReviewConstants.js} +32 -20
  35. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js.map +1 -0
  36. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewErrors.d.ts +12 -0
  37. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewErrors.js +32 -0
  38. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewErrors.js.map +1 -0
  39. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewSchemas.d.ts → codeReviewSchemas.d.ts} +6 -6
  40. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewSchemas.js → codeReviewSchemas.js} +15 -15
  41. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewSchemas.js.map +1 -0
  42. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewTypes.d.ts → codeReviewTypes.d.ts} +22 -1
  43. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.js +15 -0
  44. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.js.map +1 -0
  45. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewUtils.d.ts → codeReviewUtils.d.ts} +16 -14
  46. package/out/language-server/agenticChat/tools/qCodeAnalysis/{qCodeReviewUtils.js → codeReviewUtils.js} +38 -46
  47. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.js.map +1 -0
  48. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.d.ts +89 -0
  49. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js +138 -0
  50. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js.map +1 -0
  51. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.d.ts +14 -0
  52. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js +40 -0
  53. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js.map +1 -0
  54. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.d.ts +177 -0
  55. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js +93 -0
  56. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js.map +1 -0
  57. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.d.ts +27 -0
  58. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js +12 -0
  59. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js.map +1 -0
  60. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.d.ts +17 -0
  61. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js +33 -0
  62. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js.map +1 -0
  63. package/out/language-server/agenticChat/tools/toolServer.js +30 -10
  64. package/out/language-server/agenticChat/tools/toolServer.js.map +1 -1
  65. package/out/language-server/agenticChat/utils/commandParser.d.ts +17 -0
  66. package/out/language-server/agenticChat/utils/commandParser.js +85 -0
  67. package/out/language-server/agenticChat/utils/commandParser.js.map +1 -0
  68. package/out/language-server/chat/chatController.js +77 -0
  69. package/out/language-server/chat/chatController.js.map +1 -1
  70. package/out/language-server/chat/chatSessionService.js +19 -5
  71. package/out/language-server/chat/chatSessionService.js.map +1 -1
  72. package/out/language-server/chat/constants.d.ts +1 -0
  73. package/out/language-server/chat/constants.js +2 -1
  74. package/out/language-server/chat/constants.js.map +1 -1
  75. package/out/language-server/chat/telemetry/chatTelemetryController.d.ts +4 -2
  76. package/out/language-server/chat/telemetry/chatTelemetryController.js +13 -2
  77. package/out/language-server/chat/telemetry/chatTelemetryController.js.map +1 -1
  78. package/out/language-server/chat/utils.js +6 -0
  79. package/out/language-server/chat/utils.js.map +1 -1
  80. package/out/language-server/configuration/qConfigurationServer.d.ts +2 -1
  81. package/out/language-server/configuration/qConfigurationServer.js.map +1 -1
  82. package/out/language-server/inline-completion/auto-trigger/autoTrigger.js +2 -1
  83. package/out/language-server/inline-completion/auto-trigger/autoTrigger.js.map +1 -1
  84. package/out/language-server/inline-completion/codeWhispererServer.js +48 -143
  85. package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
  86. package/out/language-server/inline-completion/telemetry.d.ts +9 -0
  87. package/out/language-server/inline-completion/telemetry.js +109 -0
  88. package/out/language-server/inline-completion/telemetry.js.map +1 -0
  89. package/out/language-server/netTransform/validation.d.ts +5 -0
  90. package/out/language-server/netTransform/validation.js +9 -2
  91. package/out/language-server/netTransform/validation.js.map +1 -1
  92. package/out/language-server/workspaceContext/artifactManager.d.ts +1 -0
  93. package/out/language-server/workspaceContext/artifactManager.js +55 -19
  94. package/out/language-server/workspaceContext/artifactManager.js.map +1 -1
  95. package/out/language-server/workspaceContext/workspaceContextServer.js +2 -0
  96. package/out/language-server/workspaceContext/workspaceContextServer.js.map +1 -1
  97. package/out/language-server/workspaceContext/workspaceFolderManager.d.ts +3 -0
  98. package/out/language-server/workspaceContext/workspaceFolderManager.js +24 -5
  99. package/out/language-server/workspaceContext/workspaceFolderManager.js.map +1 -1
  100. package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.d.ts +1 -0
  101. package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js +16 -7
  102. package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js.map +1 -1
  103. package/out/shared/amazonQServiceManager/qDeveloperProfiles.js +48 -5
  104. package/out/shared/amazonQServiceManager/qDeveloperProfiles.js.map +1 -1
  105. package/out/shared/codeWhispererService.js +1 -0
  106. package/out/shared/codeWhispererService.js.map +1 -1
  107. package/out/shared/languageDetection.d.ts +14 -0
  108. package/out/shared/languageDetection.js +20 -0
  109. package/out/shared/languageDetection.js.map +1 -1
  110. package/out/shared/localProjectContextController.js +1 -3
  111. package/out/shared/localProjectContextController.js.map +1 -1
  112. package/out/shared/models/constants.js +2 -1
  113. package/out/shared/models/constants.js.map +1 -1
  114. package/out/shared/supplementalContextUtil/crossFileContextUtil.d.ts +4 -4
  115. package/out/shared/supplementalContextUtil/crossFileContextUtil.js +112 -18
  116. package/out/shared/supplementalContextUtil/crossFileContextUtil.js.map +1 -1
  117. package/out/shared/supplementalContextUtil/supplementalContextUtil.d.ts +1 -1
  118. package/out/shared/supplementalContextUtil/supplementalContextUtil.js +2 -2
  119. package/out/shared/supplementalContextUtil/supplementalContextUtil.js.map +1 -1
  120. package/out/shared/telemetry/telemetryService.js +36 -17
  121. package/out/shared/telemetry/telemetryService.js.map +1 -1
  122. package/out/shared/telemetry/types.d.ts +19 -1
  123. package/out/shared/telemetry/types.js +8 -1
  124. package/out/shared/telemetry/types.js.map +1 -1
  125. package/out/shared/utils.d.ts +12 -0
  126. package/out/shared/utils.js +53 -3
  127. package/out/shared/utils.js.map +1 -1
  128. package/package.json +4 -4
  129. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReview.js.map +0 -1
  130. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewConstants.js.map +0 -1
  131. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.d.ts +0 -12
  132. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.js +0 -32
  133. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.js.map +0 -1
  134. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewSchemas.js.map +0 -1
  135. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewTypes.js +0 -3
  136. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewTypes.js.map +0 -1
  137. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewUtils.js.map +0 -1
@@ -18,6 +18,7 @@ class McpEventHandler {
18
18
  #isProgrammaticChange = false;
19
19
  #debounceTimer = null;
20
20
  #lastProgrammaticState = false;
21
+ #serverNameBeforeUpdate;
21
22
  constructor(features, telemetryService) {
22
23
  this.#features = features;
23
24
  this.#eventListenerRegistered = false;
@@ -186,11 +187,15 @@ class McpEventHandler {
186
187
  * Handles MCP server click events
187
188
  */
188
189
  async onMcpServerClick(params) {
189
- this.#features.logging.log(`[VSCode Server] onMcpServerClick event with params: ${JSON.stringify(params)}`);
190
+ this.#features.logging.log(`onMcpServerClick event with params: ${JSON.stringify(params)}`);
190
191
  // Use a map of handlers for different action types
191
192
  const handlers = {
192
- 'add-new-mcp': () => this.#handleAddNewMcp(params),
193
+ 'add-new-mcp': () => {
194
+ this.#currentEditingServerName = undefined;
195
+ return this.#handleAddNewMcp(params);
196
+ },
193
197
  'save-mcp': () => this.#handleSaveMcp(params),
198
+ 'change-transport': () => this.#handleChangeTransport(params),
194
199
  'open-mcp-server': () => this.#handleOpenMcpServer(params),
195
200
  'edit-mcp': () => this.#handleEditMcpServer(params),
196
201
  'mcp-permission-change': () => this.#handleMcpPermissionChange(params),
@@ -225,27 +230,19 @@ class McpEventHandler {
225
230
  }
226
231
  async #handleAddNewMcp(params, error) {
227
232
  const existingValues = params.optionsValues || {};
228
- let argsValue = [
229
- {
230
- persistent: true,
231
- value: { arg_key: '' },
232
- },
233
- ];
233
+ // Arguments (stdio)
234
+ let argsValue = [{ persistent: true, value: { arg_key: '' } }];
234
235
  if (existingValues.args && Array.isArray(existingValues.args)) {
235
236
  argsValue = existingValues.args.map((arg, index) => ({
236
237
  persistent: index === 0,
237
- value: {
238
- arg_key: arg.arg_key || '',
239
- },
238
+ value: { arg_key: arg.arg_key || '' },
240
239
  }));
241
240
  }
241
+ // Environment variables (stdio)
242
242
  let envVarsValue = [
243
243
  {
244
244
  persistent: true,
245
- value: {
246
- env_var_name: '',
247
- env_var_value: '',
248
- },
245
+ value: { env_var_name: '', env_var_value: '' },
249
246
  },
250
247
  ];
251
248
  if (existingValues.env_variables && Array.isArray(existingValues.env_variables)) {
@@ -257,6 +254,17 @@ class McpEventHandler {
257
254
  },
258
255
  }));
259
256
  }
257
+ // Headers (http)
258
+ let headersValue = [];
259
+ if (existingValues.headers && Array.isArray(existingValues.headers)) {
260
+ headersValue = existingValues.headers.map(hdr => ({
261
+ persistent: false, // allow every row to be deleted
262
+ value: {
263
+ key: hdr.key || '',
264
+ value: hdr.value || '',
265
+ },
266
+ }));
267
+ }
260
268
  if (existingValues.name) {
261
269
  const serverName = existingValues.name;
262
270
  const sanitizedServerName = (0, mcpUtils_1.sanitizeName)(serverName);
@@ -274,114 +282,116 @@ class McpEventHandler {
274
282
  }
275
283
  }
276
284
  const serverStatusError = this.#getServerStatusError(existingValues.name) || {};
285
+ // Determine which transport is selected (default to stdio)
286
+ const selectedTransport = existingValues.transport || 'stdio';
277
287
  return {
278
288
  id: params.id,
279
289
  header: {
280
290
  title: 'Add MCP Server',
281
- status: error
282
- ? {
283
- title: error,
284
- icon: 'cancel-circle',
285
- status: 'error',
286
- }
287
- : serverStatusError,
291
+ status: error ? { title: error, icon: 'cancel-circle', status: 'error' } : serverStatusError,
288
292
  actions: [],
289
293
  },
290
294
  list: [],
291
295
  filterActions: [
292
- {
293
- id: 'cancel-mcp',
294
- text: 'Cancel',
295
- },
296
- {
297
- id: 'save-mcp',
298
- text: 'Save',
299
- status: error ? 'error' : 'primary',
300
- },
296
+ { id: 'cancel-mcp', text: 'Cancel' },
297
+ { id: 'save-mcp', text: 'Save', status: error ? 'error' : 'primary' },
301
298
  ],
302
- filterOptions: [
303
- {
304
- type: 'radiogroup',
305
- id: 'scope',
306
- title: 'Scope',
307
- options: [
299
+ filterOptions: (() => {
300
+ const common = [
301
+ {
302
+ type: 'radiogroup',
303
+ id: 'scope',
304
+ title: 'Scope',
305
+ options: [
306
+ { label: 'Global - Used globally.', value: 'global' },
307
+ { label: 'This workspace - Only used in this workspace.', value: 'workspace' },
308
+ ],
309
+ value: existingValues.scope || 'global',
310
+ },
311
+ {
312
+ type: 'textinput',
313
+ id: 'name',
314
+ title: 'Name',
315
+ value: existingValues.name || '',
316
+ mandatory: true,
317
+ },
318
+ {
319
+ type: 'select',
320
+ id: 'transport',
321
+ title: 'Transport',
322
+ mandatory: true,
323
+ options: [
324
+ { label: 'stdio', value: 'stdio' },
325
+ { label: 'http', value: 'http' },
326
+ ],
327
+ value: selectedTransport,
328
+ },
329
+ ];
330
+ if (selectedTransport === 'http') {
331
+ return [
332
+ ...common,
308
333
  {
309
- label: `Global - Used globally.`,
310
- value: 'global',
334
+ type: 'textinput',
335
+ id: 'url',
336
+ title: 'URL',
337
+ value: existingValues.url || '',
338
+ mandatory: true,
311
339
  },
312
340
  {
313
- label: `This workspace - Only used in this workspace.`,
314
- value: 'workspace',
341
+ type: 'list',
342
+ id: 'headers',
343
+ title: 'Headers - optional',
344
+ items: [
345
+ { id: 'key', title: 'Key', type: 'textinput' },
346
+ { id: 'value', title: 'Value', type: 'textinput' },
347
+ ],
348
+ ...(headersValue.length > 0 ? { value: headersValue } : {}),
315
349
  },
316
- ],
317
- value: existingValues.scope || 'global',
318
- },
319
- {
320
- type: 'textinput',
321
- id: 'name',
322
- title: 'Name',
323
- value: existingValues.name || '',
324
- mandatory: true,
325
- },
326
- {
327
- type: 'select',
328
- id: 'transport',
329
- title: 'Transport',
330
- mandatory: true,
331
- options: [
332
350
  {
333
- label: 'stdio',
334
- value: 'yes',
351
+ type: 'numericinput',
352
+ id: 'timeout',
353
+ title: 'Timeout - use 0 to disable',
354
+ value: existingValues.timeout || 60,
335
355
  },
336
- ],
337
- },
338
- {
339
- type: 'textinput',
340
- id: 'command',
341
- title: 'Command',
342
- value: existingValues.command || '',
343
- mandatory: true,
344
- },
345
- {
346
- type: 'list',
347
- id: 'args',
348
- title: 'Arguments - optional',
349
- mandatory: false,
350
- items: [
356
+ ];
357
+ }
358
+ else {
359
+ // stdio transport
360
+ return [
361
+ ...common,
351
362
  {
352
- id: 'arg_key',
353
363
  type: 'textinput',
364
+ id: 'command',
365
+ title: 'Command',
366
+ value: existingValues.command || '',
367
+ mandatory: true,
354
368
  },
355
- ],
356
- value: argsValue,
357
- },
358
- {
359
- type: 'list',
360
- id: 'env_variables',
361
- title: 'Environment variables - optional',
362
- mandatory: false,
363
- items: [
364
369
  {
365
- id: 'env_var_name',
366
- title: 'Name',
367
- type: 'textinput',
370
+ type: 'list',
371
+ id: 'args',
372
+ title: 'Arguments - optional',
373
+ items: [{ id: 'arg_key', type: 'textinput' }],
374
+ value: argsValue,
368
375
  },
369
376
  {
370
- id: 'env_var_value',
371
- title: 'Value',
372
- type: 'textinput',
377
+ type: 'list',
378
+ id: 'env_variables',
379
+ title: 'Environment variables - optional',
380
+ items: [
381
+ { id: 'env_var_name', title: 'Name', type: 'textinput' },
382
+ { id: 'env_var_value', title: 'Value', type: 'textinput' },
383
+ ],
384
+ value: envVarsValue,
373
385
  },
374
- ],
375
- value: envVarsValue,
376
- },
377
- {
378
- type: 'numericinput',
379
- id: 'timeout',
380
- title: 'Timeout - use 0 to disable',
381
- value: existingValues.timeout || 60, // Default to 60 seconds in UI
382
- mandatory: false,
383
- },
384
- ],
386
+ {
387
+ type: 'numericinput',
388
+ id: 'timeout',
389
+ title: 'Timeout - use 0 to disable',
390
+ value: existingValues.timeout || 60,
391
+ },
392
+ ];
393
+ }
394
+ })(),
385
395
  };
386
396
  }
387
397
  /**
@@ -404,6 +414,8 @@ class McpEventHandler {
404
414
  timeout: config.timeout?.toString() || '',
405
415
  env: config.env,
406
416
  args: config.args,
417
+ url: config.url,
418
+ headers: config.headers,
407
419
  };
408
420
  const validation = this.#validateMcpServerForm(values, false);
409
421
  if (!validation.isValid) {
@@ -453,8 +465,18 @@ class McpEventHandler {
453
465
  }
454
466
  }
455
467
  }
456
- if (!values.command || values.command.trim() === '') {
457
- errors.push('Command is required for stdio transport');
468
+ const transport = values.transport;
469
+ const command = values.command?.trim() || '';
470
+ const url = values.url?.trim() || '';
471
+ // Basic validation for command/url presence and exclusivity
472
+ if (!command && !url) {
473
+ errors.push('Either command or url is required');
474
+ }
475
+ else if (command && url) {
476
+ errors.push('Provide either command OR url, not both');
477
+ }
478
+ else if (transport && ((transport === 'stdio' && !command) || (transport !== 'stdio' && !url))) {
479
+ errors.push(`${transport === 'stdio' ? 'Command' : 'URL'} is required for ${transport} transport`);
458
480
  }
459
481
  if (values.timeout && values.timeout.trim() !== '') {
460
482
  const timeoutNum = Number(values.timeout.trim());
@@ -478,6 +500,20 @@ class McpEventHandler {
478
500
  errors.push('Environment variable value cannot be empty when name is provided');
479
501
  }
480
502
  }
503
+ if (Array.isArray(values.headers)) {
504
+ const hdrs = values.headers;
505
+ const invalidHeaders = hdrs.find(h => {
506
+ const key = h.key?.trim() || '';
507
+ const value = h.value?.trim() || '';
508
+ return (key === '' && value !== '') || (key !== '' && value === '');
509
+ });
510
+ if (invalidHeaders) {
511
+ const hasKey = invalidHeaders.key?.trim();
512
+ errors.push(hasKey
513
+ ? 'Header value cannot be empty when key is provided'
514
+ : 'Header key cannot be empty when value is provided');
515
+ }
516
+ }
481
517
  return {
482
518
  isValid: errors.length === 0,
483
519
  errors,
@@ -490,6 +526,7 @@ class McpEventHandler {
490
526
  if (!params.optionsValues) {
491
527
  return this.#getDefaultMcpResponse(params.id);
492
528
  }
529
+ const selectedTransport = params.optionsValues.transport;
493
530
  const serverName = params.optionsValues.name;
494
531
  const sanitizedServerName = (0, mcpUtils_1.sanitizeName)(serverName);
495
532
  const originalServerName = this.#currentEditingServerName;
@@ -498,55 +535,75 @@ class McpEventHandler {
498
535
  const validation = this.#validateMcpServerForm(params.optionsValues, true, isEditMode ? originalServerName : undefined);
499
536
  if (!validation.isValid) {
500
537
  const error = validation.errors[0];
501
- if (isEditMode) {
502
- params.id = 'edit-mcp';
503
- params.title = originalServerName;
504
- return this.#handleEditMcpServer(params, error);
505
- }
506
- else {
507
- params.id = 'add-new-mcp';
508
- return this.#handleAddNewMcp(params, error);
509
- }
538
+ params.id = isEditMode ? 'edit-mcp' : 'add-new-mcp';
539
+ return isEditMode
540
+ ? this.#handleEditMcpServer({ ...params, title: originalServerName }, error)
541
+ : this.#handleAddNewMcp(params, error);
510
542
  }
511
- // Process args to string[]
543
+ // stdio‑specific parsing
512
544
  let args = [];
513
- const argsValue = params.optionsValues.args;
514
- // Handle the case where argsValue might be a direct array or another type
515
- try {
516
- // Try to safely access and process the value
517
- const argsArray = Array.isArray(argsValue) ? argsValue : [];
518
- args = argsArray
519
- .map((item) => {
520
- return typeof item === 'object' && item !== null && 'arg_key' in item ? String(item.arg_key) : '';
521
- })
522
- .filter(Boolean);
523
- }
524
- catch (e) {
525
- this.#features.logging.warn(`Failed to process args: ${e}`);
526
- }
527
- // Process env_variables to Record<string, string>
528
545
  let env = {};
529
- const envValue = params.optionsValues.env_variables;
530
- try {
531
- const envArray = Array.isArray(envValue) ? envValue : [];
532
- env = envArray.reduce((acc, item) => {
533
- if (item && typeof item === 'object' && 'env_var_name' in item && 'env_var_value' in item) {
534
- acc[String(item.env_var_name)] = String(item.env_var_value);
535
- }
536
- return acc;
537
- }, {});
546
+ if (selectedTransport === 'stdio') {
547
+ try {
548
+ args = (Array.isArray(params.optionsValues.args) ? params.optionsValues.args : [])
549
+ .map((item) => item && typeof item === 'object' && 'arg_key' in item ? String(item.arg_key) : '')
550
+ .filter(Boolean);
551
+ }
552
+ catch (e) {
553
+ this.#features.logging.warn(`MCP: Failed to process args: ${e}`);
554
+ }
555
+ try {
556
+ env = (Array.isArray(params.optionsValues.env_variables) ? params.optionsValues.env_variables : []).reduce((acc, item) => {
557
+ if (item && 'env_var_name' in item && 'env_var_value' in item) {
558
+ acc[String(item.env_var_name)] = String(item.env_var_value);
559
+ }
560
+ return acc;
561
+ }, {});
562
+ }
563
+ catch (e) {
564
+ this.#features.logging.warn(`MCP: Failed to process env variables: ${e}`);
565
+ }
538
566
  }
539
- catch (e) {
540
- this.#features.logging.warn(`Failed to process env variables: ${e}`);
567
+ // http‑specific parsing
568
+ let headers = {};
569
+ if (selectedTransport === 'http') {
570
+ try {
571
+ const raw = Array.isArray(params.optionsValues.headers) ? params.optionsValues.headers : [];
572
+ headers = raw.reduce((acc, item) => {
573
+ const k = item.key?.toString().trim() ?? '';
574
+ const v = item.value?.toString().trim() ?? '';
575
+ // both empty → skip
576
+ if (k === '' && v === '') {
577
+ return acc;
578
+ }
579
+ // otherwise keep (validation layer handles partial-empty cases)
580
+ acc[k] = item.value ?? '';
581
+ return acc;
582
+ }, {});
583
+ }
584
+ catch (e) {
585
+ this.#features.logging.warn(`MCP: Failed to process headers: ${e}`);
586
+ }
541
587
  }
542
588
  // Config file requires timeout in milliseconds
543
589
  const timeoutInMs = (parseInt(params.optionsValues.timeout) ?? 60) * 1000;
544
- const config = {
545
- command: params.optionsValues.command,
546
- args,
547
- env,
548
- timeout: timeoutInMs,
549
- };
590
+ // build final config (no transport field persisted)
591
+ let config;
592
+ if (selectedTransport === 'http') {
593
+ config = {
594
+ url: params.optionsValues.url,
595
+ headers,
596
+ timeout: timeoutInMs,
597
+ };
598
+ }
599
+ else {
600
+ config = {
601
+ command: params.optionsValues.command,
602
+ args,
603
+ env,
604
+ timeout: timeoutInMs,
605
+ };
606
+ }
550
607
  // Get agent path based on scope
551
608
  const isGlobal = params.optionsValues['scope'] === 'global';
552
609
  const agentPath = await this.#getAgentPath(isGlobal);
@@ -558,7 +615,8 @@ class McpEventHandler {
558
615
  this.#isProgrammaticChange = true;
559
616
  try {
560
617
  if (isEditMode && originalServerName) {
561
- await mcpManager_1.McpManager.instance.removeServer(originalServerName);
618
+ const serverToRemove = this.#serverNameBeforeUpdate || originalServerName;
619
+ await mcpManager_1.McpManager.instance.removeServer(serverToRemove);
562
620
  await mcpManager_1.McpManager.instance.addServer(serverName, config, agentPath);
563
621
  }
564
622
  else {
@@ -573,14 +631,14 @@ class McpEventHandler {
573
631
  this.#currentEditingServerName = undefined;
574
632
  // need to check server state now, as there is possibility of error during server initialization
575
633
  const serverStatusError = this.#getServerStatusError(serverName);
576
- // Emit telemetry event regardless of success/failure
577
634
  this.#telemetryController?.emitMCPServerInitializeEvent({
578
635
  source: isEditMode ? 'updateServer' : 'addServer',
579
- command: config.command,
636
+ command: selectedTransport === 'stdio' ? params.optionsValues.command : undefined,
637
+ url: selectedTransport === 'http' ? params.optionsValues.url : undefined,
580
638
  enabled: true,
581
639
  numTools: mcpManager_1.McpManager.instance.getAllToolsWithPermissions(serverName).length,
582
640
  scope: params.optionsValues['scope'] === 'global' ? 'global' : 'workspace',
583
- transportType: 'stdio',
641
+ transportType: selectedTransport,
584
642
  languageServerVersion: this.#features.runtime.serverInfo.version,
585
643
  });
586
644
  if (serverStatusError) {
@@ -780,18 +838,28 @@ class McpEventHandler {
780
838
  list: [],
781
839
  };
782
840
  }
841
+ // Respect a user flip first; otherwise fall back to what the stored configuration implies.
842
+ const transport = params.optionsValues?.transport ?? (config.url ? 'http' : 'stdio');
843
+ // Convert stored structures to UI‑friendly lists
844
+ const argsList = (config.args ?? []).map(a => ({ arg_key: a })); // for stdio
845
+ const envList = Object.entries(config.env ?? {}).map(([k, v]) => ({
846
+ env_var_name: k,
847
+ env_var_value: v,
848
+ })); // for stdio
849
+ const headersList = Object.entries(config.headers ?? {}).map(([k, v]) => ({
850
+ key: k,
851
+ value: v,
852
+ })); // for http
783
853
  // UI must display timeout to user in seconds
784
854
  const timeoutInSeconds = params.optionsValues?.timeout || Math.floor((config.timeout ?? 60000) / 1000).toString();
785
855
  const existingValues = {
786
856
  name: params.optionsValues?.name || serverName,
787
- transport: 'stdio',
857
+ transport,
788
858
  command: params.optionsValues?.command || config.command,
789
- args: params.optionsValues?.args || (config.args ?? []).map(a => ({ arg_key: a })),
790
- env_variables: params.optionsValues?.env_variables ||
791
- Object.entries(config.env ?? {}).map(([k, v]) => ({
792
- env_var_name: k,
793
- env_var_value: v,
794
- })),
859
+ args: params.optionsValues?.args || argsList,
860
+ env_variables: params.optionsValues?.env_variables || envList,
861
+ url: params.optionsValues?.url || config.url,
862
+ headers: params.optionsValues?.headers || headersList,
795
863
  timeout: timeoutInSeconds,
796
864
  scope: params.optionsValues?.scope,
797
865
  };
@@ -828,6 +896,30 @@ class McpEventHandler {
828
896
  });
829
897
  return filterOptions;
830
898
  }
899
+ async #handleChangeTransport(params) {
900
+ const { optionsValues, title } = params;
901
+ const editingServerName = this.#currentEditingServerName;
902
+ // Clean up transport-specific fields
903
+ if (optionsValues) {
904
+ const transport = optionsValues.transport ?? 'stdio'; // Maintain default to 'stdio'
905
+ const fieldsToDelete = transport === 'http' ? ['command', 'args', 'env_variables'] : ['url', 'headers'];
906
+ fieldsToDelete.forEach(field => delete optionsValues[field]);
907
+ }
908
+ // Handle server name change in edit mode
909
+ if (editingServerName && title && editingServerName !== title) {
910
+ const servers = mcpManager_1.McpManager.instance.getAllServerConfigs();
911
+ const existingConfig = servers.get(editingServerName);
912
+ if (existingConfig) {
913
+ const updatedServers = new Map(servers);
914
+ updatedServers.delete(editingServerName);
915
+ updatedServers.set(title, existingConfig);
916
+ await mcpManager_1.McpManager.instance.updateServerMap(updatedServers);
917
+ }
918
+ this.#serverNameBeforeUpdate = editingServerName;
919
+ }
920
+ params.id = editingServerName ? 'edit-mcp' : 'add-new-mcp';
921
+ return editingServerName ? this.#handleEditMcpServer(params) : this.#handleAddNewMcp(params);
922
+ }
831
923
  /**
832
924
  * Gets the current permission setting for a tool
833
925
  */
@@ -888,13 +980,13 @@ class McpEventHandler {
888
980
  }
889
981
  try {
890
982
  // Skip server config check for Built-in server
983
+ const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
891
984
  if (serverName !== 'Built-in') {
892
- const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
893
985
  if (!serverConfig) {
894
986
  throw new Error(`Server '${serverName}' not found`);
895
987
  }
896
988
  }
897
- const mcpServerPermission = await this.#processPermissionUpdates(updatedPermissionConfig);
989
+ const mcpServerPermission = await this.#processPermissionUpdates(updatedPermissionConfig, serverConfig?.__configPath__);
898
990
  // Store the permission config instead of applying it immediately
899
991
  this.#pendingPermissionConfig = {
900
992
  serverName,
@@ -928,23 +1020,24 @@ class McpEventHandler {
928
1020
  const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
929
1021
  if (serverConfig) {
930
1022
  // Emit server initialize event after permission change
1023
+ const transportType = serverConfig.command ? 'stdio' : 'http';
931
1024
  this.#telemetryController?.emitMCPServerInitializeEvent({
932
1025
  source: 'updatePermission',
933
- command: serverConfig.command,
1026
+ command: transportType === 'stdio' ? serverConfig.command : undefined,
1027
+ url: transportType === 'http' ? serverConfig.url : undefined,
934
1028
  enabled: true,
935
1029
  numTools: mcpManager_1.McpManager.instance.getAllToolsWithPermissions(serverName).length,
936
1030
  scope: serverConfig.__configPath__ ===
937
1031
  (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir())
938
1032
  ? 'global'
939
1033
  : 'workspace',
940
- transportType: 'stdio',
1034
+ transportType: transportType,
941
1035
  languageServerVersion: this.#features.runtime.serverInfo.version,
942
1036
  });
943
1037
  }
944
1038
  // Clear the pending permission config after applying
945
1039
  this.#pendingPermissionConfig = undefined;
946
1040
  this.#features.logging.info(`Applied permission changes for server: ${serverName}`);
947
- this.#isProgrammaticChange = false;
948
1041
  return { id: params.id };
949
1042
  }
950
1043
  catch (error) {
@@ -987,10 +1080,12 @@ class McpEventHandler {
987
1080
  });
988
1081
  // Emit server initialize events for all active servers
989
1082
  for (const [serverName, config] of serverConfigs.entries()) {
1083
+ const transportType = config.command ? 'stdio' : 'http';
990
1084
  // const enabled = !mcpManager.isServerDisabled(serverName)
991
1085
  this.#telemetryController?.emitMCPServerInitializeEvent({
992
1086
  source: 'reload',
993
- command: config.command,
1087
+ command: transportType === 'stdio' ? config.command : undefined,
1088
+ url: transportType === 'http' ? config.url : undefined,
994
1089
  enabled: true,
995
1090
  numTools: mcpManager.getAllToolsWithPermissions(serverName).length,
996
1091
  scope: config.__configPath__ === globalAgentPath ? 'global' : 'workspace',
@@ -1057,9 +1152,7 @@ class McpEventHandler {
1057
1152
  /**
1058
1153
  * Processes permission updates from the UI
1059
1154
  */
1060
- async #processPermissionUpdates(updatedPermissionConfig) {
1061
- // Get the appropriate agent path
1062
- const agentPath = await this.#getAgentPath();
1155
+ async #processPermissionUpdates(updatedPermissionConfig, agentPath) {
1063
1156
  const perm = {
1064
1157
  enabled: true,
1065
1158
  toolPerms: {},