@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
|
@@ -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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
|
244
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
|
|
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,
|
|
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 = `@${
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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 = `@${
|
|
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
|
-
|
|
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
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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
|
-
|
|
685
|
-
|
|
686
|
-
|
|
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
|
-
|
|
795
|
-
|
|
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
|