@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.
- package/CHANGELOG.md +52 -0
- package/out/language-server/agenticChat/agenticChatController.js +27 -8
- package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
- package/out/language-server/agenticChat/constants/modelSelection.js +1 -1
- package/out/language-server/agenticChat/constants/modelSelection.js.map +1 -1
- package/out/language-server/agenticChat/tools/chatDb/chatDb.d.ts +7 -1
- package/out/language-server/agenticChat/tools/chatDb/chatDb.js +64 -17
- package/out/language-server/agenticChat/tools/chatDb/chatDb.js.map +1 -1
- package/out/language-server/agenticChat/tools/chatDb/util.d.ts +3 -2
- package/out/language-server/agenticChat/tools/chatDb/util.js.map +1 -1
- package/out/language-server/agenticChat/tools/executeBash.d.ts +4 -1
- package/out/language-server/agenticChat/tools/executeBash.js +61 -24
- package/out/language-server/agenticChat/tools/executeBash.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js +279 -181
- package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpManager.d.ts +38 -17
- package/out/language-server/agenticChat/tools/mcp/mcpManager.js +263 -110
- package/out/language-server/agenticChat/tools/mcp/mcpManager.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpTypes.d.ts +4 -1
- package/out/language-server/agenticChat/tools/mcp/mcpTypes.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.d.ts +1 -2
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.js +106 -28
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.d.ts +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js +10 -15
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.d.ts +2 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js +3 -2
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.d.ts +6 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.js +9 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewUtils.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.d.ts +89 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js +138 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindings.js.map +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.d.ts +14 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js +41 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsConstants.js.map +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.d.ts +177 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js +93 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.js.map +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.d.ts +27 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js +12 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsTypes.js.map +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.d.ts +17 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js +33 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsUtils.js.map +1 -0
- package/out/language-server/agenticChat/tools/toolServer.js +22 -2
- package/out/language-server/agenticChat/tools/toolServer.js.map +1 -1
- package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js +1 -1
- package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js.map +1 -1
- package/out/language-server/agenticChat/utils/commandParser.d.ts +17 -0
- package/out/language-server/agenticChat/utils/commandParser.js +85 -0
- package/out/language-server/agenticChat/utils/commandParser.js.map +1 -0
- package/out/language-server/chat/chatController.js +77 -0
- package/out/language-server/chat/chatController.js.map +1 -1
- package/out/language-server/chat/chatSessionService.js +1 -1
- package/out/language-server/chat/chatSessionService.js.map +1 -1
- package/out/language-server/chat/constants.d.ts +1 -0
- package/out/language-server/chat/constants.js +2 -1
- package/out/language-server/chat/constants.js.map +1 -1
- package/out/language-server/chat/telemetry/chatTelemetryController.d.ts +2 -0
- package/out/language-server/chat/telemetry/chatTelemetryController.js +12 -0
- package/out/language-server/chat/telemetry/chatTelemetryController.js.map +1 -1
- package/out/language-server/chat/utils.js +6 -0
- package/out/language-server/chat/utils.js.map +1 -1
- package/out/language-server/configuration/qConfigurationServer.d.ts +1 -0
- package/out/language-server/configuration/qConfigurationServer.js.map +1 -1
- package/out/language-server/inline-completion/auto-trigger/autoTrigger.js +2 -1
- package/out/language-server/inline-completion/auto-trigger/autoTrigger.js.map +1 -1
- package/out/language-server/inline-completion/codeDiffTracker.d.ts +9 -0
- package/out/language-server/inline-completion/codeDiffTracker.js.map +1 -1
- package/out/language-server/inline-completion/codeWhispererServer.d.ts +0 -3
- package/out/language-server/inline-completion/codeWhispererServer.js +80 -201
- package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
- package/out/language-server/inline-completion/constants.d.ts +9 -0
- package/out/language-server/inline-completion/constants.js +10 -0
- package/out/language-server/inline-completion/constants.js.map +1 -0
- package/out/language-server/inline-completion/documentChangedListener.d.ts +8 -0
- package/out/language-server/inline-completion/documentChangedListener.js +20 -0
- package/out/language-server/inline-completion/documentChangedListener.js.map +1 -0
- package/out/language-server/inline-completion/editCompletionHandler.d.ts +49 -0
- package/out/language-server/inline-completion/editCompletionHandler.js +320 -0
- package/out/language-server/inline-completion/editCompletionHandler.js.map +1 -0
- package/out/language-server/inline-completion/session/sessionManager.d.ts +10 -2
- package/out/language-server/inline-completion/session/sessionManager.js +34 -7
- package/out/language-server/inline-completion/session/sessionManager.js.map +1 -1
- package/out/language-server/inline-completion/telemetry.js +12 -2
- package/out/language-server/inline-completion/telemetry.js.map +1 -1
- package/out/language-server/inline-completion/trigger.d.ts +17 -0
- package/out/language-server/inline-completion/trigger.js +42 -0
- package/out/language-server/inline-completion/trigger.js.map +1 -0
- package/out/language-server/workspaceContext/artifactManager.js +25 -6
- package/out/language-server/workspaceContext/artifactManager.js.map +1 -1
- package/out/shared/codeWhispererService.d.ts +36 -1
- package/out/shared/codeWhispererService.js +77 -0
- package/out/shared/codeWhispererService.js.map +1 -1
- package/out/shared/constants.d.ts +1 -0
- package/out/shared/constants.js +2 -1
- package/out/shared/constants.js.map +1 -1
- package/out/shared/languageDetection.js +0 -2
- package/out/shared/languageDetection.js.map +1 -1
- package/out/shared/models/constants.js +2 -1
- package/out/shared/models/constants.js.map +1 -1
- package/out/shared/supplementalContextUtil/crossFileContextUtil.d.ts +5 -6
- package/out/shared/supplementalContextUtil/crossFileContextUtil.js +114 -10
- package/out/shared/supplementalContextUtil/crossFileContextUtil.js.map +1 -1
- package/out/shared/supplementalContextUtil/supplementalContextUtil.d.ts +1 -2
- package/out/shared/supplementalContextUtil/supplementalContextUtil.js +2 -2
- package/out/shared/supplementalContextUtil/supplementalContextUtil.js.map +1 -1
- package/out/shared/telemetry/telemetryService.js +42 -18
- package/out/shared/telemetry/telemetryService.js.map +1 -1
- package/out/shared/telemetry/types.d.ts +16 -1
- package/out/shared/telemetry/types.js +2 -0
- package/out/shared/telemetry/types.js.map +1 -1
- package/out/shared/utils.d.ts +13 -0
- package/out/shared/utils.js +60 -4
- package/out/shared/utils.js.map +1 -1
- 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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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': () =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
-
|
|
310
|
-
|
|
336
|
+
type: 'textinput',
|
|
337
|
+
id: 'url',
|
|
338
|
+
title: 'URL',
|
|
339
|
+
value: existingValues.url || '',
|
|
340
|
+
mandatory: true,
|
|
311
341
|
},
|
|
312
342
|
{
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
334
|
-
|
|
353
|
+
type: 'numericinput',
|
|
354
|
+
id: 'timeout',
|
|
355
|
+
title: 'Timeout - use 0 to disable',
|
|
356
|
+
value: existingValues.timeout || 60,
|
|
335
357
|
},
|
|
336
|
-
]
|
|
337
|
-
}
|
|
338
|
-
{
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
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
|
-
|
|
457
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
params
|
|
504
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
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
|
-
|
|
540
|
-
|
|
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
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
861
|
+
transport,
|
|
788
862
|
command: params.optionsValues?.command || config.command,
|
|
789
|
-
args: params.optionsValues?.args ||
|
|
790
|
-
env_variables: params.optionsValues?.env_variables ||
|
|
791
|
-
|
|
792
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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: {},
|