@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
@@ -8,6 +8,8 @@ exports.McpManager = exports.AGENT_TOOLS_CHANGED = exports.MCP_SERVER_STATUS_CHA
8
8
  const types_1 = require("../../../../shared/telemetry/types");
9
9
  const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
10
10
  const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
11
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
12
+ const sse_js_1 = require("@modelcontextprotocol/sdk/client/sse.js");
11
13
  const mcpTypes_1 = require("./mcpTypes");
12
14
  const mcpUtils_1 = require("./mcpUtils");
13
15
  const errors_1 = require("../../errors");
@@ -15,6 +17,7 @@ const events_1 = require("events");
15
17
  const async_mutex_1 = require("async-mutex");
16
18
  const path = require("path");
17
19
  const vscode_uri_1 = require("vscode-uri");
20
+ const utils_1 = require("../../../../shared/utils");
18
21
  exports.MCP_SERVER_STATUS_CHANGED = 'mcpServerStatusChanged';
19
22
  exports.AGENT_TOOLS_CHANGED = 'agentToolsChanged';
20
23
  /**
@@ -58,7 +61,7 @@ class McpManager {
58
61
  features.logging.info(`MCP: discovered ${mgr.mcpTools.length} tools across all servers`);
59
62
  // Emit MCP configuration metrics
60
63
  const serverConfigs = mgr.getAllServerConfigs();
61
- const activeServers = Array.from(serverConfigs.entries());
64
+ const activeServers = Array.from(serverConfigs.entries()).filter(([name, _]) => !mgr.isServerDisabled(name));
62
65
  // Count global vs project servers
63
66
  const globalServers = Array.from(serverConfigs.entries()).filter(([_, config]) => config?.__configPath__ === (0, mcpUtils_1.getGlobalAgentConfigPath)(features.workspace.fs.getUserHomeDir())).length;
64
67
  const projectServers = serverConfigs.size - globalServers;
@@ -179,6 +182,12 @@ class McpManager {
179
182
  // Get all servers that need to be initialized
180
183
  const serversToInit = [];
181
184
  for (const [name, cfg] of this.mcpServers.entries()) {
185
+ if (this.isServerDisabled(name)) {
186
+ this.features.logging.info(`MCP: server '${name}' is disabled by persona settings, skipping`);
187
+ this.setState(name, mcpTypes_1.McpServerStatus.DISABLED, 0);
188
+ this.emitToolsChanged(name);
189
+ continue;
190
+ }
182
191
  serversToInit.push([name, cfg]);
183
192
  }
184
193
  // Process servers in batches of 5 at a time
@@ -205,57 +214,91 @@ class McpManager {
205
214
  this.setState(serverName, mcpTypes_1.McpServerStatus.INITIALIZING, 0);
206
215
  try {
207
216
  this.features.logging.debug(`MCP: initializing server [${serverName}]`);
208
- const mergedEnv = {
209
- ...process.env,
210
- // Make sure we do not have empty key and value in mergedEnv, or adding server through UI will fail on Windows
211
- ...(cfg.env && !(0, mcpUtils_1.isEmptyEnv)(cfg.env)
212
- ? Object.fromEntries(Object.entries(cfg.env).filter(([key]) => key && key.trim() !== ''))
213
- : {}),
214
- };
215
- const transportConfig = {
216
- command: cfg.command,
217
- args: cfg.args ?? [],
218
- env: mergedEnv,
219
- };
220
- try {
221
- const workspaceFolders = this.features.workspace.getAllWorkspaceFolders();
222
- if (workspaceFolders.length > 0) {
223
- transportConfig.cwd = vscode_uri_1.URI.parse(workspaceFolders[0].uri).fsPath;
224
- }
225
- }
226
- catch {
227
- this.features.logging.debug(`MCP: No workspace folder available for server [${serverName}], continuing without cwd`);
228
- }
229
- const transport = new stdio_js_1.StdioClientTransport(transportConfig);
230
217
  const client = new index_js_1.Client({
231
218
  name: `mcp-client-${serverName}`,
232
219
  version: '1.0.0',
233
220
  });
234
- const connectPromise = client.connect(transport).catch(err => {
235
- let errorMessage = err.message;
236
- // Provide specific guidance for common command not found errors
237
- if (err.code === 'ENOENT') {
238
- errorMessage = `Command '${cfg.command}' not found. Please ensure it's installed and available in your PATH.`;
239
- }
240
- else if (err.code === 'EINVAL') {
241
- errorMessage = `Invalid arguments. Please check the command and arguments.`;
221
+ let transport;
222
+ const isStdio = !!cfg.command;
223
+ const doConnect = async () => {
224
+ if (isStdio) {
225
+ const mergedEnv = {
226
+ ...process.env,
227
+ // Make sure we do not have empty key and value in mergedEnv, or adding server through UI will fail on Windows
228
+ ...(cfg.env && !(0, mcpUtils_1.isEmptyEnv)(cfg.env)
229
+ ? Object.fromEntries(Object.entries(cfg.env).filter(([k, v]) => k.trim() && v.trim()))
230
+ : {}),
231
+ };
232
+ let cwd;
233
+ try {
234
+ const folders = this.features.workspace.getAllWorkspaceFolders();
235
+ if (folders.length > 0)
236
+ cwd = vscode_uri_1.URI.parse(folders[0].uri).fsPath;
237
+ }
238
+ catch {
239
+ this.features.logging.debug(`MCP: no workspace folder for [${serverName}], continuing without cwd`);
240
+ }
241
+ transport = new stdio_js_1.StdioClientTransport({
242
+ command: cfg.command,
243
+ args: cfg.args ?? [],
244
+ env: mergedEnv,
245
+ cwd,
246
+ });
247
+ this.features.logging.info(`MCP: Connecting MCP server using StdioClientTransport`);
248
+ try {
249
+ await client.connect(transport);
250
+ }
251
+ catch (err) {
252
+ let errorMessage = err?.message ?? String(err);
253
+ if (err?.code === 'ENOENT') {
254
+ errorMessage = `Command '${cfg.command}' not found. Please ensure it's installed and on your PATH.`;
255
+ }
256
+ else if (err?.code === 'EINVAL') {
257
+ errorMessage = `Invalid arguments for command '${cfg.command}'.`;
258
+ }
259
+ else if (err?.code === -32000) {
260
+ errorMessage = `MCP protocol error. The server may not be properly configured.`;
261
+ }
262
+ throw new errors_1.AgenticChatError(`MCP: server '${serverName}' failed to connect: ${errorMessage}`, 'MCPServerConnectionFailed');
263
+ }
242
264
  }
243
- else if (err.code === -32000) {
244
- errorMessage = `MCP protocol error. The server may not be properly configured.`;
265
+ else {
266
+ const base = new URL(cfg.url);
267
+ try {
268
+ try {
269
+ // try streamable http first
270
+ transport = new streamableHttp_js_1.StreamableHTTPClientTransport(base, this.buildHttpOpts(cfg.headers));
271
+ this.features.logging.info(`MCP: Connecting MCP server using StreamableHTTPClientTransport`);
272
+ await client.connect(transport);
273
+ }
274
+ catch (err) {
275
+ // fallback to SSE
276
+ this.features.logging.info(`MCP: streamable http connect failed for [${serverName}], fallback to SSEClientTransport: ${String(err)}`);
277
+ transport = new sse_js_1.SSEClientTransport(new URL(cfg.url), this.buildSseOpts(cfg.headers));
278
+ await client.connect(transport);
279
+ }
280
+ }
281
+ catch (err) {
282
+ let errorMessage = err?.message ?? String(err);
283
+ throw new errors_1.AgenticChatError(`MCP: server '${serverName}' failed to connect: ${errorMessage}`, 'MCPServerConnectionFailed');
284
+ }
245
285
  }
246
- throw new errors_1.AgenticChatError(`MCP: server '${serverName}' failed to connect: ${errorMessage}`, 'MCPServerConnectionFailed');
247
- });
248
- // 0 or undefined -> no timeout
249
- if (cfg.initializationTimeout === 0 || cfg.initializationTimeout === undefined) {
250
- await connectPromise;
286
+ };
287
+ const connectPromise = doConnect();
288
+ const timeoutMs = cfg.initializationTimeout === 0 || cfg.initializationTimeout === undefined
289
+ ? 0
290
+ : (cfg.initializationTimeout ?? DEFAULT_SERVER_INIT_TIMEOUT_MS);
291
+ if (timeoutMs > 0) {
292
+ await Promise.race([
293
+ connectPromise,
294
+ new Promise((_, reject) => {
295
+ const t = setTimeout(() => reject(new errors_1.AgenticChatError(`MCP: server '${serverName}' initialization timed out after ${timeoutMs} ms`, 'MCPServerInitTimeout')), timeoutMs);
296
+ t.unref();
297
+ }),
298
+ ]);
251
299
  }
252
300
  else {
253
- const timeoutMs = cfg.initializationTimeout ?? DEFAULT_SERVER_INIT_TIMEOUT_MS;
254
- const timeoutPromise = new Promise((_, reject) => {
255
- const timer = setTimeout(() => reject(new errors_1.AgenticChatError(`MCP: server '${serverName}' initialization timed out after ${timeoutMs} ms`, 'MCPServerInitTimeout')), timeoutMs);
256
- timer.unref();
257
- });
258
- await Promise.race([connectPromise, timeoutPromise]);
301
+ await connectPromise;
259
302
  }
260
303
  this.clients.set(serverName, client);
261
304
  this.mcpTools = this.mcpTools.filter(t => t.serverName !== serverName);
@@ -269,7 +312,7 @@ class McpManager {
269
312
  this.mcpTools.push({
270
313
  serverName,
271
314
  toolName: t.name,
272
- description: (0, mcpUtils_1.sanitizeContent)(t.description ?? ''),
315
+ description: (0, utils_1.sanitizeInput)(t.description ?? ''),
273
316
  inputSchema: t.inputSchema ?? {},
274
317
  });
275
318
  }
@@ -287,6 +330,12 @@ class McpManager {
287
330
  this.handleError(serverName, e);
288
331
  }
289
332
  }
333
+ /**
334
+ * Update server map
335
+ */
336
+ updateServerMap(newMap) {
337
+ this.mcpServers = new Map(newMap);
338
+ }
290
339
  /**
291
340
  * Return a list of all discovered tools.
292
341
  */
@@ -310,7 +359,7 @@ class McpManager {
310
359
  * Return a list of all enabled tools.
311
360
  */
312
361
  getEnabledTools() {
313
- return this.mcpTools.filter(t => !this.isToolDisabled(t.serverName, t.toolName));
362
+ return this.mcpTools.filter(t => !this.isServerDisabled(t.serverName) && !this.isToolDisabled(t.serverName, t.toolName));
314
363
  }
315
364
  /**
316
365
  * Returns true if the given tool on the given server is currently disabled.
@@ -320,8 +369,10 @@ class McpManager {
320
369
  if (server === 'builtIn') {
321
370
  return false;
322
371
  }
372
+ // Get unsanitized server name for prefix
373
+ const unsanitizedServerName = this.serverNameMapping.get(server) || server;
323
374
  // Check if the server is enabled as a whole (@server)
324
- const serverPrefix = `@${server}`;
375
+ const serverPrefix = `@${unsanitizedServerName}`;
325
376
  const isWholeServerEnabled = this.agentConfig.tools.includes(serverPrefix);
326
377
  // Check if the specific tool is enabled
327
378
  const toolId = `${serverPrefix}/${tool}`;
@@ -336,16 +387,10 @@ class McpManager {
336
387
  /**
337
388
  * Returns true if the given server is currently disabled.
338
389
  */
339
- // public isServerDisabled(name: string): boolean {
340
- // // Check if any tool from this server is enabled
341
- // return !this.agentConfig.tools.some(tool => {
342
- // if (tool.startsWith('@')) {
343
- // // Check if it's the server itself or a tool from the server
344
- // return tool === `@${name}` || tool.startsWith(`@${name}/`)
345
- // }
346
- // return false
347
- // })
348
- // }
390
+ isServerDisabled(name) {
391
+ const cfg = this.mcpServers.get(name);
392
+ return cfg?.disabled ?? false;
393
+ }
349
394
  /**
350
395
  * Returns tool permission type for a given tool.
351
396
  */
@@ -354,8 +399,10 @@ class McpManager {
354
399
  if (server === 'builtIn') {
355
400
  return this.agentConfig.allowedTools.includes(tool) ? mcpTypes_1.McpPermissionType.alwaysAllow : mcpTypes_1.McpPermissionType.ask;
356
401
  }
402
+ // Get unsanitized server name for prefix
403
+ const unsanitizedServerName = this.serverNameMapping.get(server) || server;
357
404
  // Check if the server is enabled as a whole (@server)
358
- const serverPrefix = `@${server}`;
405
+ const serverPrefix = `@${unsanitizedServerName}`;
359
406
  const isWholeServerEnabled = this.agentConfig.tools.includes(serverPrefix);
360
407
  // Check if the specific tool is enabled
361
408
  const toolId = `${serverPrefix}/${tool}`;
@@ -404,7 +451,8 @@ class McpManager {
404
451
  const cfg = this.mcpServers.get(server);
405
452
  if (!cfg)
406
453
  throw new Error(`MCP: server '${server}' is not configured`);
407
- // if (this.isServerDisabled(server)) throw new Error(`MCP: server '${server}' is disabled`)
454
+ if (this.isServerDisabled(server))
455
+ throw new Error(`MCP: server '${server}' is disabled`);
408
456
  const available = this.getEnabledTools()
409
457
  .filter(t => t.serverName === server)
410
458
  .map(t => t.toolName);
@@ -448,7 +496,9 @@ class McpManager {
448
496
  // Add server to agent config
449
497
  const serverConfig = {
450
498
  command: cfg.command,
499
+ url: cfg.url,
451
500
  initializationTimeout: cfg.initializationTimeout,
501
+ disabled: cfg.disabled ?? false,
452
502
  };
453
503
  // Only add timeout to agent config if it's not 0
454
504
  if (cfg.timeout !== 0) {
@@ -460,6 +510,9 @@ class McpManager {
460
510
  if (cfg.env && !(0, mcpUtils_1.isEmptyEnv)(cfg.env)) {
461
511
  serverConfig.env = cfg.env;
462
512
  }
513
+ if (cfg.headers && !(0, mcpUtils_1.isEmptyEnv)(cfg.headers)) {
514
+ serverConfig.headers = cfg.headers;
515
+ }
463
516
  // Add to agent config
464
517
  this.agentConfig.mcpServers[serverName] = serverConfig;
465
518
  // We don't need to store configPath anymore as we're using agent config
@@ -475,7 +528,7 @@ class McpManager {
475
528
  this.agentConfig.tools.push(serverPrefix);
476
529
  }
477
530
  // Save agent config once with all changes
478
- await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath);
531
+ await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath, serverName);
479
532
  // Add server tools to tools list after initialization
480
533
  await this.initOneServer(sanitizedName, newCfg);
481
534
  }
@@ -531,7 +584,7 @@ class McpManager {
531
584
  return true;
532
585
  });
533
586
  // Save agent config
534
- await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, cfg.__configPath__);
587
+ await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, cfg.__configPath__, unsanitizedName);
535
588
  // Get all config paths and delete the server from each one
536
589
  const wsUris = this.features.workspace.getAllWorkspaceFolders()?.map(f => f.uri) ?? [];
537
590
  const wsConfigPaths = (0, mcpUtils_1.getWorkspaceMcpConfigPaths)(wsUris);
@@ -569,6 +622,16 @@ class McpManager {
569
622
  // Update agent config
570
623
  if (this.agentConfig && unsanitizedServerName) {
571
624
  const updatedConfig = { ...(this.agentConfig.mcpServers[unsanitizedServerName] || {}) };
625
+ if (configUpdates.url !== undefined)
626
+ updatedConfig.url = configUpdates.url;
627
+ if (configUpdates.headers !== undefined) {
628
+ if (configUpdates.headers && Object.keys(configUpdates.headers).length) {
629
+ updatedConfig.headers = configUpdates.headers;
630
+ }
631
+ else {
632
+ delete updatedConfig.headers; // allow user to clear headers
633
+ }
634
+ }
572
635
  if (configUpdates.command !== undefined)
573
636
  updatedConfig.command = configUpdates.command;
574
637
  if (configUpdates.initializationTimeout !== undefined)
@@ -591,9 +654,12 @@ class McpManager {
591
654
  delete updatedConfig.env;
592
655
  }
593
656
  }
657
+ if (configUpdates.disabled !== undefined) {
658
+ updatedConfig.disabled = configUpdates.disabled;
659
+ }
594
660
  this.agentConfig.mcpServers[unsanitizedServerName] = updatedConfig;
595
661
  // Save agent config
596
- await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath);
662
+ await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath, unsanitizedServerName);
597
663
  }
598
664
  const newCfg = {
599
665
  ...oldCfg,
@@ -607,13 +673,13 @@ class McpManager {
607
673
  this.mcpTools = this.mcpTools.filter(t => t.serverName !== serverName);
608
674
  this.mcpServers.set(serverName, newCfg);
609
675
  this.serverNameMapping.set(serverName, unsanitizedServerName);
610
- // if (this.isServerDisabled(serverName)) {
611
- // this.setState(serverName, McpServerStatus.DISABLED, 0)
612
- // this.emitToolsChanged(serverName)
613
- // } else {
614
- // await this.initOneServer(serverName, newCfg)
615
- // }
616
- await this.initOneServer(serverName, newCfg);
676
+ if (this.isServerDisabled(serverName)) {
677
+ this.setState(serverName, mcpTypes_1.McpServerStatus.DISABLED, 0);
678
+ this.emitToolsChanged(serverName);
679
+ }
680
+ else {
681
+ await this.initOneServer(serverName, newCfg);
682
+ }
617
683
  }
618
684
  catch (err) {
619
685
  this.handleError(serverName, err);
@@ -681,10 +747,10 @@ class McpManager {
681
747
  try {
682
748
  const unsanitizedServerName = this.serverNameMapping.get(serverName) || serverName;
683
749
  // Get server config
684
- // const serverConfig = this.mcpServers.get(serverName)
685
- // if (!serverConfig) {
686
- // throw new Error(`Server '${serverName}' not found`)
687
- // }
750
+ const serverConfig = this.mcpServers.get(serverName);
751
+ if (!serverConfig) {
752
+ throw new Error(`Server '${serverName}' not found`);
753
+ }
688
754
  const serverPrefix = `@${unsanitizedServerName}`;
689
755
  // Track tools that should be enabled
690
756
  const toolsToEnable = new Set();
@@ -768,16 +834,38 @@ class McpManager {
768
834
  this.agentConfig.allowedTools.push(toolId);
769
835
  }
770
836
  }
837
+ // Update server enabled/disabled state in agent config
838
+ if (this.agentConfig.mcpServers[unsanitizedServerName]) {
839
+ this.agentConfig.mcpServers[unsanitizedServerName].disabled = !perm.enabled;
840
+ }
841
+ // Also update the mcpServers map
842
+ if (serverConfig) {
843
+ serverConfig.disabled = !perm.enabled;
844
+ }
771
845
  // Save agent config
772
846
  const agentPath = perm.__configPath__;
773
847
  if (agentPath) {
774
- await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath);
848
+ await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, agentPath, unsanitizedServerName);
775
849
  }
776
850
  // Update mcpServerPermissions map
777
851
  this.mcpServerPermissions.set(serverName, {
778
852
  enabled: perm.enabled,
779
853
  toolPerms: perm.toolPerms || {},
780
854
  });
855
+ // enable/disable server
856
+ if (this.isServerDisabled(serverName)) {
857
+ const client = this.clients.get(serverName);
858
+ if (client) {
859
+ await client.close();
860
+ this.clients.delete(serverName);
861
+ }
862
+ this.setState(serverName, mcpTypes_1.McpServerStatus.DISABLED, 0);
863
+ }
864
+ else {
865
+ if (!this.clients.has(serverName)) {
866
+ await this.initOneServer(serverName, this.mcpServers.get(serverName));
867
+ }
868
+ }
781
869
  this.features.logging.info(`Permissions updated for '${serverName}' in agent config`);
782
870
  this.emitToolsChanged(serverName);
783
871
  }
@@ -791,42 +879,13 @@ class McpManager {
791
879
  */
792
880
  requiresApproval(server, tool) {
793
881
  // For built-in tools, check directly without prefix
794
- const toolId = server === 'builtIn' ? tool : `@${server}/${tool}`;
795
- return !this.agentConfig.allowedTools.includes(toolId);
796
- }
797
- /**
798
- * Updates the runtime state for a given server, including status, tool count, and optional error message.
799
- * This is used by the UI to reflect real-time server status.
800
- * @private
801
- */
802
- setState(server, status, toolsCount, lastError) {
803
- const st = { status, toolsCount, lastError };
804
- this.mcpServerStates.set(server, st);
805
- this.events.emit(exports.MCP_SERVER_STATUS_CHANGED, server, { ...st });
806
- }
807
- /**
808
- * Emits an event when the tools associated with a server change.
809
- * Used to refresh the Agent's tool list.
810
- * @private
811
- */
812
- emitToolsChanged(server) {
813
- const enabled = this.getEnabledTools()
814
- .filter(t => t.serverName === server)
815
- .map(t => ({ ...t }));
816
- this.features.logging.debug(`ToolsChanged | server=${server} | toolCount=${enabled.length}`);
817
- this.events.emit(exports.AGENT_TOOLS_CHANGED, server, enabled);
818
- }
819
- /**
820
- * Centralized error handling: logs the error, updates the status, and emits an event.
821
- * Exceptions are no longer thrown to ensure the remaining workflow continues uninterrupted.
822
- */
823
- handleError(server, err) {
824
- const msg = err instanceof Error ? err.message : String(err);
825
- this.features.logging.error(`MCP ERROR${server ? ` [${server}]` : ''}: ${msg}`);
826
- if (server) {
827
- this.setState(server, mcpTypes_1.McpServerStatus.FAILED, 0, msg);
828
- this.emitToolsChanged(server);
882
+ if (server === 'builtIn') {
883
+ return !this.agentConfig.allowedTools.includes(tool);
829
884
  }
885
+ // Get unsanitized server name for prefix
886
+ const unsanitizedServerName = this.serverNameMapping.get(server) || server;
887
+ const toolId = `@${unsanitizedServerName}/${tool}`;
888
+ return !this.agentConfig.allowedTools.includes(toolId);
830
889
  }
831
890
  /**
832
891
  * Returns any errors that occurred during loading of MCP configuration files
@@ -880,7 +939,7 @@ class McpManager {
880
939
  return true;
881
940
  });
882
941
  // Save agent config
883
- await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, cfg.__configPath__);
942
+ await (0, mcpUtils_1.saveAgentConfig)(this.features.workspace, this.features.logging, this.agentConfig, cfg.__configPath__, unsanitizedName);
884
943
  }
885
944
  }
886
945
  catch (err) {
@@ -950,6 +1009,100 @@ class McpManager {
950
1009
  setToolNameMapping(mapping) {
951
1010
  this.toolNameMapping = new Map(mapping);
952
1011
  }
1012
+ /**
1013
+ * Updates the runtime state for a given server, including status, tool count, and optional error message.
1014
+ * This is used by the UI to reflect real-time server status.
1015
+ * @private
1016
+ */
1017
+ setState(server, status, toolsCount, lastError) {
1018
+ const st = { status, toolsCount, lastError };
1019
+ this.mcpServerStates.set(server, st);
1020
+ this.events.emit(exports.MCP_SERVER_STATUS_CHANGED, server, { ...st });
1021
+ }
1022
+ /**
1023
+ * Emits an event when the tools associated with a server change.
1024
+ * Used to refresh the Agent's tool list.
1025
+ * @private
1026
+ */
1027
+ emitToolsChanged(server) {
1028
+ const enabled = this.getEnabledTools()
1029
+ .filter(t => t.serverName === server)
1030
+ .map(t => ({ ...t }));
1031
+ this.features.logging.debug(`ToolsChanged | server=${server} | toolCount=${enabled.length}`);
1032
+ this.events.emit(exports.AGENT_TOOLS_CHANGED, server, enabled);
1033
+ }
1034
+ /**
1035
+ * Centralized error handling: logs the error, updates the status, and emits an event.
1036
+ * Exceptions are no longer thrown to ensure the remaining workflow continues uninterrupted.
1037
+ */
1038
+ handleError(server, err) {
1039
+ const msg = err instanceof Error ? err.message : String(err);
1040
+ this.features.logging.error(`MCP ERROR${server ? ` [${server}]` : ''}: ${msg}`);
1041
+ if (server) {
1042
+ this.setState(server, mcpTypes_1.McpServerStatus.FAILED, 0, msg);
1043
+ this.emitToolsChanged(server);
1044
+ }
1045
+ }
1046
+ /**
1047
+ * Ensure the server-specific config is internally consistent.
1048
+ * Mutates `cfg` in-place, trimming fields that don't belong to the selected transport.
1049
+ * @private
1050
+ */
1051
+ validateServerCfg(cfg) {
1052
+ const hasCmd = !!cfg.command?.trim();
1053
+ const hasUrl = !!cfg.url?.trim();
1054
+ if (hasCmd && hasUrl)
1055
+ throw new Error('Specify either command or url, not both');
1056
+ if (!hasCmd && !hasUrl)
1057
+ throw new Error('Either command or url is required');
1058
+ if (hasCmd) {
1059
+ if (!cfg.command.trim())
1060
+ throw new Error('Stdio transport requires "command"');
1061
+ delete cfg.url;
1062
+ delete cfg.headers;
1063
+ }
1064
+ else {
1065
+ if (!cfg.url.trim())
1066
+ throw new Error('HTTP transport requires "url"');
1067
+ delete cfg.command;
1068
+ delete cfg.args;
1069
+ delete cfg.env;
1070
+ }
1071
+ }
1072
+ /**
1073
+ * Creates the option bag for SSEClientTransport
1074
+ * @private
1075
+ */
1076
+ buildSseOpts(headers) {
1077
+ if (!headers || Object.keys(headers).length === 0) {
1078
+ return;
1079
+ }
1080
+ const requestInit = { headers };
1081
+ // override only the SSE‐GET:
1082
+ const eventSourceInit = {
1083
+ fetch: (input, init = {}) => {
1084
+ const merged = new Headers(init.headers || {});
1085
+ for (const [k, v] of Object.entries(headers)) {
1086
+ merged.set(k, v);
1087
+ }
1088
+ return fetch(input, {
1089
+ ...init,
1090
+ headers: merged,
1091
+ });
1092
+ },
1093
+ };
1094
+ return { requestInit, eventSourceInit };
1095
+ }
1096
+ /**
1097
+ * Creates the option bag for StreamableHTTPClientTransport
1098
+ * @private
1099
+ */
1100
+ buildHttpOpts(headers) {
1101
+ if (!headers || Object.keys(headers).length === 0) {
1102
+ return;
1103
+ }
1104
+ return { requestInit: { headers } };
1105
+ }
953
1106
  }
954
1107
  exports.McpManager = McpManager;
955
1108
  //# sourceMappingURL=mcpManager.js.map