@aws/lsp-codewhisperer 0.0.70 → 0.0.72

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 (119) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/out/language-server/agenticChat/agenticChatController.js +27 -8
  3. package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
  4. package/out/language-server/agenticChat/constants/modelSelection.js +1 -1
  5. package/out/language-server/agenticChat/constants/modelSelection.js.map +1 -1
  6. package/out/language-server/agenticChat/tools/chatDb/chatDb.d.ts +7 -1
  7. package/out/language-server/agenticChat/tools/chatDb/chatDb.js +64 -17
  8. package/out/language-server/agenticChat/tools/chatDb/chatDb.js.map +1 -1
  9. package/out/language-server/agenticChat/tools/chatDb/util.d.ts +3 -2
  10. package/out/language-server/agenticChat/tools/chatDb/util.js.map +1 -1
  11. package/out/language-server/agenticChat/tools/executeBash.d.ts +4 -1
  12. package/out/language-server/agenticChat/tools/executeBash.js +61 -24
  13. package/out/language-server/agenticChat/tools/executeBash.js.map +1 -1
  14. package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js +279 -181
  15. package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js.map +1 -1
  16. package/out/language-server/agenticChat/tools/mcp/mcpManager.d.ts +38 -17
  17. package/out/language-server/agenticChat/tools/mcp/mcpManager.js +263 -110
  18. package/out/language-server/agenticChat/tools/mcp/mcpManager.js.map +1 -1
  19. package/out/language-server/agenticChat/tools/mcp/mcpTypes.d.ts +4 -1
  20. package/out/language-server/agenticChat/tools/mcp/mcpTypes.js.map +1 -1
  21. package/out/language-server/agenticChat/tools/mcp/mcpUtils.d.ts +1 -2
  22. package/out/language-server/agenticChat/tools/mcp/mcpUtils.js +106 -28
  23. package/out/language-server/agenticChat/tools/mcp/mcpUtils.js.map +1 -1
  24. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.d.ts +1 -0
  25. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js +10 -15
  26. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js.map +1 -1
  27. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.d.ts +2 -1
  28. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js +3 -2
  29. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js.map +1 -1
  30. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.d.ts +6 -0
  31. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.js +9 -0
  32. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.js.map +1 -1
  33. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.d.ts +89 -0
  34. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js +138 -0
  35. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js.map +1 -0
  36. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.d.ts +14 -0
  37. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js +41 -0
  38. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js.map +1 -0
  39. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.d.ts +177 -0
  40. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js +93 -0
  41. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js.map +1 -0
  42. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.d.ts +27 -0
  43. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js +12 -0
  44. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js.map +1 -0
  45. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.d.ts +17 -0
  46. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js +33 -0
  47. package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js.map +1 -0
  48. package/out/language-server/agenticChat/tools/toolServer.js +22 -2
  49. package/out/language-server/agenticChat/tools/toolServer.js.map +1 -1
  50. package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js +1 -1
  51. package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js.map +1 -1
  52. package/out/language-server/agenticChat/utils/commandParser.d.ts +17 -0
  53. package/out/language-server/agenticChat/utils/commandParser.js +85 -0
  54. package/out/language-server/agenticChat/utils/commandParser.js.map +1 -0
  55. package/out/language-server/chat/chatController.js +77 -0
  56. package/out/language-server/chat/chatController.js.map +1 -1
  57. package/out/language-server/chat/chatSessionService.js +1 -1
  58. package/out/language-server/chat/chatSessionService.js.map +1 -1
  59. package/out/language-server/chat/constants.d.ts +1 -0
  60. package/out/language-server/chat/constants.js +2 -1
  61. package/out/language-server/chat/constants.js.map +1 -1
  62. package/out/language-server/chat/telemetry/chatTelemetryController.d.ts +2 -0
  63. package/out/language-server/chat/telemetry/chatTelemetryController.js +12 -0
  64. package/out/language-server/chat/telemetry/chatTelemetryController.js.map +1 -1
  65. package/out/language-server/chat/utils.js +6 -0
  66. package/out/language-server/chat/utils.js.map +1 -1
  67. package/out/language-server/configuration/qConfigurationServer.d.ts +1 -0
  68. package/out/language-server/configuration/qConfigurationServer.js.map +1 -1
  69. package/out/language-server/inline-completion/auto-trigger/autoTrigger.js +2 -1
  70. package/out/language-server/inline-completion/auto-trigger/autoTrigger.js.map +1 -1
  71. package/out/language-server/inline-completion/codeDiffTracker.d.ts +9 -0
  72. package/out/language-server/inline-completion/codeDiffTracker.js.map +1 -1
  73. package/out/language-server/inline-completion/codeWhispererServer.d.ts +0 -3
  74. package/out/language-server/inline-completion/codeWhispererServer.js +80 -201
  75. package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
  76. package/out/language-server/inline-completion/constants.d.ts +9 -0
  77. package/out/language-server/inline-completion/constants.js +10 -0
  78. package/out/language-server/inline-completion/constants.js.map +1 -0
  79. package/out/language-server/inline-completion/documentChangedListener.d.ts +8 -0
  80. package/out/language-server/inline-completion/documentChangedListener.js +20 -0
  81. package/out/language-server/inline-completion/documentChangedListener.js.map +1 -0
  82. package/out/language-server/inline-completion/editCompletionHandler.d.ts +49 -0
  83. package/out/language-server/inline-completion/editCompletionHandler.js +320 -0
  84. package/out/language-server/inline-completion/editCompletionHandler.js.map +1 -0
  85. package/out/language-server/inline-completion/session/sessionManager.d.ts +10 -2
  86. package/out/language-server/inline-completion/session/sessionManager.js +34 -7
  87. package/out/language-server/inline-completion/session/sessionManager.js.map +1 -1
  88. package/out/language-server/inline-completion/telemetry.js +12 -2
  89. package/out/language-server/inline-completion/telemetry.js.map +1 -1
  90. package/out/language-server/inline-completion/trigger.d.ts +17 -0
  91. package/out/language-server/inline-completion/trigger.js +42 -0
  92. package/out/language-server/inline-completion/trigger.js.map +1 -0
  93. package/out/language-server/workspaceContext/artifactManager.js +25 -6
  94. package/out/language-server/workspaceContext/artifactManager.js.map +1 -1
  95. package/out/shared/codeWhispererService.d.ts +36 -1
  96. package/out/shared/codeWhispererService.js +77 -0
  97. package/out/shared/codeWhispererService.js.map +1 -1
  98. package/out/shared/constants.d.ts +1 -0
  99. package/out/shared/constants.js +2 -1
  100. package/out/shared/constants.js.map +1 -1
  101. package/out/shared/languageDetection.js +0 -2
  102. package/out/shared/languageDetection.js.map +1 -1
  103. package/out/shared/models/constants.js +2 -1
  104. package/out/shared/models/constants.js.map +1 -1
  105. package/out/shared/supplementalContextUtil/crossFileContextUtil.d.ts +5 -6
  106. package/out/shared/supplementalContextUtil/crossFileContextUtil.js +114 -10
  107. package/out/shared/supplementalContextUtil/crossFileContextUtil.js.map +1 -1
  108. package/out/shared/supplementalContextUtil/supplementalContextUtil.d.ts +1 -2
  109. package/out/shared/supplementalContextUtil/supplementalContextUtil.js +2 -2
  110. package/out/shared/supplementalContextUtil/supplementalContextUtil.js.map +1 -1
  111. package/out/shared/telemetry/telemetryService.js +42 -18
  112. package/out/shared/telemetry/telemetryService.js.map +1 -1
  113. package/out/shared/telemetry/types.d.ts +16 -1
  114. package/out/shared/telemetry/types.js +2 -0
  115. package/out/shared/telemetry/types.js.map +1 -1
  116. package/out/shared/utils.d.ts +13 -0
  117. package/out/shared/utils.js +60 -4
  118. package/out/shared/utils.js.map +1 -1
  119. package/package.json +4 -4
@@ -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;
@@ -143,13 +144,15 @@ class McpEventHandler {
143
144
  },
144
145
  ],
145
146
  };
146
- // if (mcpManager.isServerDisabled(serverName)) {
147
- // disabledItems.push(item)
148
- // } else {
149
- activeItems.push({
150
- ...item,
151
- description: `${toolsCount}`,
152
- });
147
+ if (mcpManager.isServerDisabled(serverName)) {
148
+ disabledItems.push(item);
149
+ }
150
+ else {
151
+ activeItems.push({
152
+ ...item,
153
+ description: `${toolsCount}`,
154
+ });
155
+ }
153
156
  });
154
157
  // Create the groups
155
158
  const groups = [];
@@ -189,8 +192,12 @@ class McpEventHandler {
189
192
  this.#features.logging.log(`onMcpServerClick event with params: ${JSON.stringify(params)}`);
190
193
  // Use a map of handlers for different action types
191
194
  const handlers = {
192
- 'add-new-mcp': () => this.#handleAddNewMcp(params),
195
+ 'add-new-mcp': () => {
196
+ this.#currentEditingServerName = undefined;
197
+ return this.#handleAddNewMcp(params);
198
+ },
193
199
  'save-mcp': () => this.#handleSaveMcp(params),
200
+ 'change-transport': () => this.#handleChangeTransport(params),
194
201
  'open-mcp-server': () => this.#handleOpenMcpServer(params),
195
202
  'edit-mcp': () => this.#handleEditMcpServer(params),
196
203
  'mcp-permission-change': () => this.#handleMcpPermissionChange(params),
@@ -225,27 +232,19 @@ class McpEventHandler {
225
232
  }
226
233
  async #handleAddNewMcp(params, error) {
227
234
  const existingValues = params.optionsValues || {};
228
- let argsValue = [
229
- {
230
- persistent: true,
231
- value: { arg_key: '' },
232
- },
233
- ];
235
+ // Arguments (stdio)
236
+ let argsValue = [{ persistent: true, value: { arg_key: '' } }];
234
237
  if (existingValues.args && Array.isArray(existingValues.args)) {
235
238
  argsValue = existingValues.args.map((arg, index) => ({
236
239
  persistent: index === 0,
237
- value: {
238
- arg_key: arg.arg_key || '',
239
- },
240
+ value: { arg_key: arg.arg_key || '' },
240
241
  }));
241
242
  }
243
+ // Environment variables (stdio)
242
244
  let envVarsValue = [
243
245
  {
244
246
  persistent: true,
245
- value: {
246
- env_var_name: '',
247
- env_var_value: '',
248
- },
247
+ value: { env_var_name: '', env_var_value: '' },
249
248
  },
250
249
  ];
251
250
  if (existingValues.env_variables && Array.isArray(existingValues.env_variables)) {
@@ -257,6 +256,17 @@ class McpEventHandler {
257
256
  },
258
257
  }));
259
258
  }
259
+ // Headers (http)
260
+ let headersValue = [];
261
+ if (existingValues.headers && Array.isArray(existingValues.headers)) {
262
+ headersValue = existingValues.headers.map(hdr => ({
263
+ persistent: false, // allow every row to be deleted
264
+ value: {
265
+ key: hdr.key || '',
266
+ value: hdr.value || '',
267
+ },
268
+ }));
269
+ }
260
270
  if (existingValues.name) {
261
271
  const serverName = existingValues.name;
262
272
  const sanitizedServerName = (0, mcpUtils_1.sanitizeName)(serverName);
@@ -274,114 +284,116 @@ class McpEventHandler {
274
284
  }
275
285
  }
276
286
  const serverStatusError = this.#getServerStatusError(existingValues.name) || {};
287
+ // Determine which transport is selected (default to stdio)
288
+ const selectedTransport = existingValues.transport || 'stdio';
277
289
  return {
278
290
  id: params.id,
279
291
  header: {
280
292
  title: 'Add MCP Server',
281
- status: error
282
- ? {
283
- title: error,
284
- icon: 'cancel-circle',
285
- status: 'error',
286
- }
287
- : serverStatusError,
293
+ status: error ? { title: error, icon: 'cancel-circle', status: 'error' } : serverStatusError,
288
294
  actions: [],
289
295
  },
290
296
  list: [],
291
297
  filterActions: [
292
- {
293
- id: 'cancel-mcp',
294
- text: 'Cancel',
295
- },
296
- {
297
- id: 'save-mcp',
298
- text: 'Save',
299
- status: error ? 'error' : 'primary',
300
- },
298
+ { id: 'cancel-mcp', text: 'Cancel' },
299
+ { id: 'save-mcp', text: 'Save', status: error ? 'error' : 'primary' },
301
300
  ],
302
- filterOptions: [
303
- {
304
- type: 'radiogroup',
305
- id: 'scope',
306
- title: 'Scope',
307
- options: [
301
+ filterOptions: (() => {
302
+ const common = [
303
+ {
304
+ type: 'radiogroup',
305
+ id: 'scope',
306
+ title: 'Scope',
307
+ options: [
308
+ { label: 'Global - Used globally.', value: 'global' },
309
+ { label: 'This workspace - Only used in this workspace.', value: 'workspace' },
310
+ ],
311
+ value: existingValues.scope || 'global',
312
+ },
313
+ {
314
+ type: 'textinput',
315
+ id: 'name',
316
+ title: 'Name',
317
+ value: existingValues.name || '',
318
+ mandatory: true,
319
+ },
320
+ {
321
+ type: 'select',
322
+ id: 'transport',
323
+ title: 'Transport',
324
+ mandatory: true,
325
+ options: [
326
+ { label: 'stdio', value: 'stdio' },
327
+ { label: 'http', value: 'http' },
328
+ ],
329
+ value: selectedTransport,
330
+ },
331
+ ];
332
+ if (selectedTransport === 'http') {
333
+ return [
334
+ ...common,
308
335
  {
309
- label: `Global - Used globally.`,
310
- value: 'global',
336
+ type: 'textinput',
337
+ id: 'url',
338
+ title: 'URL',
339
+ value: existingValues.url || '',
340
+ mandatory: true,
311
341
  },
312
342
  {
313
- label: `This workspace - Only used in this workspace.`,
314
- value: 'workspace',
343
+ type: 'list',
344
+ id: 'headers',
345
+ title: 'Headers - optional',
346
+ items: [
347
+ { id: 'key', title: 'Key', type: 'textinput' },
348
+ { id: 'value', title: 'Value', type: 'textinput' },
349
+ ],
350
+ ...(headersValue.length > 0 ? { value: headersValue } : {}),
315
351
  },
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
352
  {
333
- label: 'stdio',
334
- value: 'yes',
353
+ type: 'numericinput',
354
+ id: 'timeout',
355
+ title: 'Timeout - use 0 to disable',
356
+ value: existingValues.timeout || 60,
335
357
  },
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: [
358
+ ];
359
+ }
360
+ else {
361
+ // stdio transport
362
+ return [
363
+ ...common,
351
364
  {
352
- id: 'arg_key',
353
365
  type: 'textinput',
366
+ id: 'command',
367
+ title: 'Command',
368
+ value: existingValues.command || '',
369
+ mandatory: true,
354
370
  },
355
- ],
356
- value: argsValue,
357
- },
358
- {
359
- type: 'list',
360
- id: 'env_variables',
361
- title: 'Environment variables - optional',
362
- mandatory: false,
363
- items: [
364
371
  {
365
- id: 'env_var_name',
366
- title: 'Name',
367
- type: 'textinput',
372
+ type: 'list',
373
+ id: 'args',
374
+ title: 'Arguments - optional',
375
+ items: [{ id: 'arg_key', type: 'textinput' }],
376
+ value: argsValue,
368
377
  },
369
378
  {
370
- id: 'env_var_value',
371
- title: 'Value',
372
- type: 'textinput',
379
+ type: 'list',
380
+ id: 'env_variables',
381
+ title: 'Environment variables - optional',
382
+ items: [
383
+ { id: 'env_var_name', title: 'Name', type: 'textinput' },
384
+ { id: 'env_var_value', title: 'Value', type: 'textinput' },
385
+ ],
386
+ value: envVarsValue,
373
387
  },
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
- ],
388
+ {
389
+ type: 'numericinput',
390
+ id: 'timeout',
391
+ title: 'Timeout - use 0 to disable',
392
+ value: existingValues.timeout || 60,
393
+ },
394
+ ];
395
+ }
396
+ })(),
385
397
  };
386
398
  }
387
399
  /**
@@ -404,6 +416,8 @@ class McpEventHandler {
404
416
  timeout: config.timeout?.toString() || '',
405
417
  env: config.env,
406
418
  args: config.args,
419
+ url: config.url,
420
+ headers: config.headers,
407
421
  };
408
422
  const validation = this.#validateMcpServerForm(values, false);
409
423
  if (!validation.isValid) {
@@ -453,8 +467,18 @@ class McpEventHandler {
453
467
  }
454
468
  }
455
469
  }
456
- if (!values.command || values.command.trim() === '') {
457
- errors.push('Command is required for stdio transport');
470
+ const transport = values.transport;
471
+ const command = values.command?.trim() || '';
472
+ const url = values.url?.trim() || '';
473
+ // Basic validation for command/url presence and exclusivity
474
+ if (!command && !url) {
475
+ errors.push('Either command or url is required');
476
+ }
477
+ else if (command && url) {
478
+ errors.push('Provide either command OR url, not both');
479
+ }
480
+ else if (transport && ((transport === 'stdio' && !command) || (transport !== 'stdio' && !url))) {
481
+ errors.push(`${transport === 'stdio' ? 'Command' : 'URL'} is required for ${transport} transport`);
458
482
  }
459
483
  if (values.timeout && values.timeout.trim() !== '') {
460
484
  const timeoutNum = Number(values.timeout.trim());
@@ -478,6 +502,20 @@ class McpEventHandler {
478
502
  errors.push('Environment variable value cannot be empty when name is provided');
479
503
  }
480
504
  }
505
+ if (Array.isArray(values.headers)) {
506
+ const hdrs = values.headers;
507
+ const invalidHeaders = hdrs.find(h => {
508
+ const key = h.key?.trim() || '';
509
+ const value = h.value?.trim() || '';
510
+ return (key === '' && value !== '') || (key !== '' && value === '');
511
+ });
512
+ if (invalidHeaders) {
513
+ const hasKey = invalidHeaders.key?.trim();
514
+ errors.push(hasKey
515
+ ? 'Header value cannot be empty when key is provided'
516
+ : 'Header key cannot be empty when value is provided');
517
+ }
518
+ }
481
519
  return {
482
520
  isValid: errors.length === 0,
483
521
  errors,
@@ -490,6 +528,7 @@ class McpEventHandler {
490
528
  if (!params.optionsValues) {
491
529
  return this.#getDefaultMcpResponse(params.id);
492
530
  }
531
+ const selectedTransport = params.optionsValues.transport;
493
532
  const serverName = params.optionsValues.name;
494
533
  const sanitizedServerName = (0, mcpUtils_1.sanitizeName)(serverName);
495
534
  const originalServerName = this.#currentEditingServerName;
@@ -498,55 +537,75 @@ class McpEventHandler {
498
537
  const validation = this.#validateMcpServerForm(params.optionsValues, true, isEditMode ? originalServerName : undefined);
499
538
  if (!validation.isValid) {
500
539
  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
- }
540
+ params.id = isEditMode ? 'edit-mcp' : 'add-new-mcp';
541
+ return isEditMode
542
+ ? this.#handleEditMcpServer({ ...params, title: originalServerName }, error)
543
+ : this.#handleAddNewMcp(params, error);
510
544
  }
511
- // Process args to string[]
545
+ // stdio‑specific parsing
512
546
  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
547
  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
- }, {});
548
+ if (selectedTransport === 'stdio') {
549
+ try {
550
+ args = (Array.isArray(params.optionsValues.args) ? params.optionsValues.args : [])
551
+ .map((item) => item && typeof item === 'object' && 'arg_key' in item ? String(item.arg_key) : '')
552
+ .filter(Boolean);
553
+ }
554
+ catch (e) {
555
+ this.#features.logging.warn(`MCP: Failed to process args: ${e}`);
556
+ }
557
+ try {
558
+ env = (Array.isArray(params.optionsValues.env_variables) ? params.optionsValues.env_variables : []).reduce((acc, item) => {
559
+ if (item && 'env_var_name' in item && 'env_var_value' in item) {
560
+ acc[String(item.env_var_name)] = String(item.env_var_value);
561
+ }
562
+ return acc;
563
+ }, {});
564
+ }
565
+ catch (e) {
566
+ this.#features.logging.warn(`MCP: Failed to process env variables: ${e}`);
567
+ }
538
568
  }
539
- catch (e) {
540
- this.#features.logging.warn(`Failed to process env variables: ${e}`);
569
+ // http‑specific parsing
570
+ let headers = {};
571
+ if (selectedTransport === 'http') {
572
+ try {
573
+ const raw = Array.isArray(params.optionsValues.headers) ? params.optionsValues.headers : [];
574
+ headers = raw.reduce((acc, item) => {
575
+ const k = item.key?.toString().trim() ?? '';
576
+ const v = item.value?.toString().trim() ?? '';
577
+ // both empty → skip
578
+ if (k === '' && v === '') {
579
+ return acc;
580
+ }
581
+ // otherwise keep (validation layer handles partial-empty cases)
582
+ acc[k] = item.value ?? '';
583
+ return acc;
584
+ }, {});
585
+ }
586
+ catch (e) {
587
+ this.#features.logging.warn(`MCP: Failed to process headers: ${e}`);
588
+ }
541
589
  }
542
590
  // Config file requires timeout in milliseconds
543
591
  const timeoutInMs = (parseInt(params.optionsValues.timeout) ?? 60) * 1000;
544
- const config = {
545
- command: params.optionsValues.command,
546
- args,
547
- env,
548
- timeout: timeoutInMs,
549
- };
592
+ // build final config (no transport field persisted)
593
+ let config;
594
+ if (selectedTransport === 'http') {
595
+ config = {
596
+ url: params.optionsValues.url,
597
+ headers,
598
+ timeout: timeoutInMs,
599
+ };
600
+ }
601
+ else {
602
+ config = {
603
+ command: params.optionsValues.command,
604
+ args,
605
+ env,
606
+ timeout: timeoutInMs,
607
+ };
608
+ }
550
609
  // Get agent path based on scope
551
610
  const isGlobal = params.optionsValues['scope'] === 'global';
552
611
  const agentPath = await this.#getAgentPath(isGlobal);
@@ -558,7 +617,8 @@ class McpEventHandler {
558
617
  this.#isProgrammaticChange = true;
559
618
  try {
560
619
  if (isEditMode && originalServerName) {
561
- await mcpManager_1.McpManager.instance.removeServer(originalServerName);
620
+ const serverToRemove = this.#serverNameBeforeUpdate || originalServerName;
621
+ await mcpManager_1.McpManager.instance.removeServer(serverToRemove);
562
622
  await mcpManager_1.McpManager.instance.addServer(serverName, config, agentPath);
563
623
  }
564
624
  else {
@@ -573,14 +633,14 @@ class McpEventHandler {
573
633
  this.#currentEditingServerName = undefined;
574
634
  // need to check server state now, as there is possibility of error during server initialization
575
635
  const serverStatusError = this.#getServerStatusError(serverName);
576
- // Emit telemetry event regardless of success/failure
577
636
  this.#telemetryController?.emitMCPServerInitializeEvent({
578
637
  source: isEditMode ? 'updateServer' : 'addServer',
579
- command: config.command,
638
+ command: selectedTransport === 'stdio' ? params.optionsValues.command : undefined,
639
+ url: selectedTransport === 'http' ? params.optionsValues.url : undefined,
580
640
  enabled: true,
581
641
  numTools: mcpManager_1.McpManager.instance.getAllToolsWithPermissions(serverName).length,
582
642
  scope: params.optionsValues['scope'] === 'global' ? 'global' : 'workspace',
583
- transportType: 'stdio',
643
+ transportType: selectedTransport,
584
644
  languageServerVersion: this.#features.runtime.serverInfo.version,
585
645
  });
586
646
  if (serverStatusError) {
@@ -686,8 +746,9 @@ class McpEventHandler {
686
746
  if (!serverName) {
687
747
  return { id: params.id };
688
748
  }
749
+ const mcpManager = mcpManager_1.McpManager.instance;
689
750
  // Get the appropriate agent path
690
- const agentPath = await this.#getAgentPath();
751
+ const agentPath = mcpManager.getAllServerConfigs().get(serverName)?.__configPath__;
691
752
  const perm = {
692
753
  enabled: true,
693
754
  toolPerms: {},
@@ -696,13 +757,13 @@ class McpEventHandler {
696
757
  // Set flag to ignore file changes during permission update
697
758
  this.#isProgrammaticChange = true;
698
759
  try {
699
- await mcpManager_1.McpManager.instance.updateServerPermission(serverName, perm);
760
+ await mcpManager.updateServerPermission(serverName, perm);
700
761
  this.#emitMCPConfigEvent();
701
762
  }
702
763
  catch (error) {
703
764
  this.#features.logging.error(`Failed to enable MCP server: ${error}`);
765
+ this.#isProgrammaticChange = false;
704
766
  }
705
- this.#isProgrammaticChange = false;
706
767
  return { id: params.id };
707
768
  }
708
769
  /**
@@ -713,8 +774,9 @@ class McpEventHandler {
713
774
  if (!serverName) {
714
775
  return { id: params.id };
715
776
  }
777
+ const mcpManager = mcpManager_1.McpManager.instance;
716
778
  // Get the appropriate agent path
717
- const agentPath = await this.#getAgentPath();
779
+ const agentPath = mcpManager.getAllServerConfigs().get(serverName)?.__configPath__;
718
780
  const perm = {
719
781
  enabled: false,
720
782
  toolPerms: {},
@@ -723,13 +785,13 @@ class McpEventHandler {
723
785
  // Set flag to ignore file changes during permission update
724
786
  this.#isProgrammaticChange = true;
725
787
  try {
726
- await mcpManager_1.McpManager.instance.updateServerPermission(serverName, perm);
788
+ await mcpManager.updateServerPermission(serverName, perm);
727
789
  this.#emitMCPConfigEvent();
728
790
  }
729
791
  catch (error) {
730
792
  this.#features.logging.error(`Failed to disable MCP server: ${error}`);
793
+ this.#isProgrammaticChange = false;
731
794
  }
732
- this.#isProgrammaticChange = false;
733
795
  return { id: params.id };
734
796
  }
735
797
  /**
@@ -780,18 +842,28 @@ class McpEventHandler {
780
842
  list: [],
781
843
  };
782
844
  }
845
+ // Respect a user flip first; otherwise fall back to what the stored configuration implies.
846
+ const transport = params.optionsValues?.transport ?? (config.url ? 'http' : 'stdio');
847
+ // Convert stored structures to UI‑friendly lists
848
+ const argsList = (config.args ?? []).map(a => ({ arg_key: a })); // for stdio
849
+ const envList = Object.entries(config.env ?? {}).map(([k, v]) => ({
850
+ env_var_name: k,
851
+ env_var_value: v,
852
+ })); // for stdio
853
+ const headersList = Object.entries(config.headers ?? {}).map(([k, v]) => ({
854
+ key: k,
855
+ value: v,
856
+ })); // for http
783
857
  // UI must display timeout to user in seconds
784
858
  const timeoutInSeconds = params.optionsValues?.timeout || Math.floor((config.timeout ?? 60000) / 1000).toString();
785
859
  const existingValues = {
786
860
  name: params.optionsValues?.name || serverName,
787
- transport: 'stdio',
861
+ transport,
788
862
  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
- })),
863
+ args: params.optionsValues?.args || argsList,
864
+ env_variables: params.optionsValues?.env_variables || envList,
865
+ url: params.optionsValues?.url || config.url,
866
+ headers: params.optionsValues?.headers || headersList,
795
867
  timeout: timeoutInSeconds,
796
868
  scope: params.optionsValues?.scope,
797
869
  };
@@ -828,6 +900,30 @@ class McpEventHandler {
828
900
  });
829
901
  return filterOptions;
830
902
  }
903
+ async #handleChangeTransport(params) {
904
+ const { optionsValues, title } = params;
905
+ const editingServerName = this.#currentEditingServerName;
906
+ // Clean up transport-specific fields
907
+ if (optionsValues) {
908
+ const transport = optionsValues.transport ?? 'stdio'; // Maintain default to 'stdio'
909
+ const fieldsToDelete = transport === 'http' ? ['command', 'args', 'env_variables'] : ['url', 'headers'];
910
+ fieldsToDelete.forEach(field => delete optionsValues[field]);
911
+ }
912
+ // Handle server name change in edit mode
913
+ if (editingServerName && title && editingServerName !== title) {
914
+ const servers = mcpManager_1.McpManager.instance.getAllServerConfigs();
915
+ const existingConfig = servers.get(editingServerName);
916
+ if (existingConfig) {
917
+ const updatedServers = new Map(servers);
918
+ updatedServers.delete(editingServerName);
919
+ updatedServers.set(title, existingConfig);
920
+ await mcpManager_1.McpManager.instance.updateServerMap(updatedServers);
921
+ }
922
+ this.#serverNameBeforeUpdate = editingServerName;
923
+ }
924
+ params.id = editingServerName ? 'edit-mcp' : 'add-new-mcp';
925
+ return editingServerName ? this.#handleEditMcpServer(params) : this.#handleAddNewMcp(params);
926
+ }
831
927
  /**
832
928
  * Gets the current permission setting for a tool
833
929
  */
@@ -888,13 +984,13 @@ class McpEventHandler {
888
984
  }
889
985
  try {
890
986
  // Skip server config check for Built-in server
987
+ const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
891
988
  if (serverName !== 'Built-in') {
892
- const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
893
989
  if (!serverConfig) {
894
990
  throw new Error(`Server '${serverName}' not found`);
895
991
  }
896
992
  }
897
- const mcpServerPermission = await this.#processPermissionUpdates(updatedPermissionConfig);
993
+ const mcpServerPermission = await this.#processPermissionUpdates(updatedPermissionConfig, serverConfig?.__configPath__);
898
994
  // Store the permission config instead of applying it immediately
899
995
  this.#pendingPermissionConfig = {
900
996
  serverName,
@@ -928,16 +1024,18 @@ class McpEventHandler {
928
1024
  const serverConfig = mcpManager_1.McpManager.instance.getAllServerConfigs().get(serverName);
929
1025
  if (serverConfig) {
930
1026
  // Emit server initialize event after permission change
1027
+ const transportType = serverConfig.command ? 'stdio' : 'http';
931
1028
  this.#telemetryController?.emitMCPServerInitializeEvent({
932
1029
  source: 'updatePermission',
933
- command: serverConfig.command,
1030
+ command: transportType === 'stdio' ? serverConfig.command : undefined,
1031
+ url: transportType === 'http' ? serverConfig.url : undefined,
934
1032
  enabled: true,
935
1033
  numTools: mcpManager_1.McpManager.instance.getAllToolsWithPermissions(serverName).length,
936
1034
  scope: serverConfig.__configPath__ ===
937
1035
  (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir())
938
1036
  ? 'global'
939
1037
  : 'workspace',
940
- transportType: 'stdio',
1038
+ transportType: transportType,
941
1039
  languageServerVersion: this.#features.runtime.serverInfo.version,
942
1040
  });
943
1041
  }
@@ -956,7 +1054,7 @@ class McpEventHandler {
956
1054
  // Emit MCP config event after reinitialization
957
1055
  const mcpManager = mcpManager_1.McpManager.instance;
958
1056
  const serverConfigs = mcpManager.getAllServerConfigs();
959
- const activeServers = Array.from(serverConfigs.entries());
1057
+ const activeServers = Array.from(serverConfigs.entries()).filter(([name, _]) => !mcpManager.isServerDisabled(name));
960
1058
  // Get the global agent path
961
1059
  const globalAgentPath = (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir());
962
1060
  // Count global vs project servers
@@ -986,11 +1084,13 @@ class McpEventHandler {
986
1084
  });
987
1085
  // Emit server initialize events for all active servers
988
1086
  for (const [serverName, config] of serverConfigs.entries()) {
989
- // const enabled = !mcpManager.isServerDisabled(serverName)
1087
+ const transportType = config.command ? 'stdio' : 'http';
1088
+ const enabled = !mcpManager.isServerDisabled(serverName);
990
1089
  this.#telemetryController?.emitMCPServerInitializeEvent({
991
1090
  source: 'reload',
992
- command: config.command,
993
- enabled: true,
1091
+ command: transportType === 'stdio' ? config.command : undefined,
1092
+ url: transportType === 'http' ? config.url : undefined,
1093
+ enabled: enabled,
994
1094
  numTools: mcpManager.getAllToolsWithPermissions(serverName).length,
995
1095
  scope: config.__configPath__ === globalAgentPath ? 'global' : 'workspace',
996
1096
  transportType: 'stdio',
@@ -1030,10 +1130,10 @@ class McpEventHandler {
1030
1130
  * @returns The agent path to use (workspace if exists, otherwise global)
1031
1131
  */
1032
1132
  async #getAgentPath(isGlobal = true) {
1133
+ const globalAgentPath = (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir());
1033
1134
  if (isGlobal) {
1034
- return (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir());
1135
+ return globalAgentPath;
1035
1136
  }
1036
- const globalAgentPath = (0, mcpUtils_1.getGlobalAgentConfigPath)(this.#features.workspace.fs.getUserHomeDir());
1037
1137
  // Get workspace folders and check for workspace agent path
1038
1138
  const workspaceFolders = this.#features.workspace.getAllWorkspaceFolders();
1039
1139
  if (workspaceFolders && workspaceFolders.length > 0) {
@@ -1056,9 +1156,7 @@ class McpEventHandler {
1056
1156
  /**
1057
1157
  * Processes permission updates from the UI
1058
1158
  */
1059
- async #processPermissionUpdates(updatedPermissionConfig) {
1060
- // Get the appropriate agent path
1061
- const agentPath = await this.#getAgentPath();
1159
+ async #processPermissionUpdates(updatedPermissionConfig, agentPath) {
1062
1160
  const perm = {
1063
1161
  enabled: true,
1064
1162
  toolPerms: {},