diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts index d6839eb6c4bc9..b66d42488e804 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts @@ -45,6 +45,7 @@ import { emptyWorkspaceInfo, getWorkingDirectory, IWorkspaceInfo } from '../../c import { buildChatHistoryFromEvents, RequestIdDetails, stripReminders } from '../common/copilotCLITools'; import { ICustomSessionTitleService } from '../common/customSessionTitleService'; import { IChatDelegationSummaryService } from '../common/delegationSummaryService'; +import { SessionIdForCLI } from '../common/utils'; import { getCopilotCLISessionDir, getCopilotCLISessionEventsFile, getCopilotCLIWorkspaceFile } from './cliHelpers'; import { getAgentFileNameFromFilePath, ICopilotCLIAgents, ICopilotCLISDK } from './copilotCli'; import { CopilotCliBridgeSpanProcessor } from './copilotCliBridgeSpanProcessor'; @@ -536,7 +537,8 @@ export class CopilotCLISessionService extends Disposable implements ICopilotCLIS } public async createSession(options: ICreateSessionOptions, token: CancellationToken): Promise { - const { mcpConfig: mcpServers, disposable: mcpGateway } = await this.mcpHandler.loadMcpConfig(); + const resource = options.sessionId ? SessionIdForCLI.getResource(options.sessionId) : URI.from({ scheme: 'copilot-cli', path: `mcp-gateway-${generateUuid()}` }); + const { mcpConfig: mcpServers, disposable: mcpGateway } = await this.mcpHandler.loadMcpConfig(resource); try { const sessionOptions = await this.createSessionsOptions({ ...options, mcpServers }); const sessionManager = await raceCancellationError(this.getSessionManager(), token); @@ -726,7 +728,7 @@ export class CopilotCLISessionService extends Disposable implements ICopilotCLIS const [sessionManager, { mcpConfig: mcpServers, disposable: mcpGateway }] = await Promise.all([ raceCancellationError(this.getSessionManager(), token), - this.mcpHandler.loadMcpConfig(), + this.mcpHandler.loadMcpConfig(SessionIdForCLI.getResource(options.sessionId)), ]); try { const sessionOptions = await this.createSessionsOptions({ ...options, mcpServers }); diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/mcpHandler.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/mcpHandler.ts index f6dcd630ead97..8d0720780e28c 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/mcpHandler.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/mcpHandler.ts @@ -13,7 +13,6 @@ import { createServiceIdentifier } from '../../../../util/common/services'; import { Disposable, DisposableStore, IDisposable } from '../../../../util/vs/base/common/lifecycle'; import { hasKey } from '../../../../util/vs/base/common/types'; import { URI } from '../../../../util/vs/base/common/uri'; -import { generateUuid } from '../../../../util/vs/base/common/uuid'; import type { LanguageModelToolInformation } from '../../../../vscodeTypes'; import { GitHubMcpDefinitionProvider } from '../../../githubMcp/common/githubMcpDefinitionProvider'; @@ -34,7 +33,7 @@ export type MCPServerConfig = NonNullable[string]; export interface ICopilotCLIMCPHandler { readonly _serviceBrand: undefined; - loadMcpConfig(): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }>; + loadMcpConfig(sessionUri: URI): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }>; } export const ICopilotCLIMCPHandler = createServiceIdentifier('ICopilotCLIMCPHandler'); @@ -48,7 +47,7 @@ export class CopilotCLIMCPHandler implements ICopilotCLIMCPHandler { @IMcpService private readonly mcpService: IMcpService, ) { } - public async loadMcpConfig(): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }> { + public async loadMcpConfig(sessionUri: URI): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }> { // TODO: Sessions window settings override is not honored with extension // configuration API, so this needs to be a core setting @@ -56,7 +55,7 @@ export class CopilotCLIMCPHandler implements ICopilotCLIMCPHandler { // Sessions window: use the gateway approach which proxies all MCP servers from core if (isSessionsWindow) { - return this.loadMcpConfigWithGateway(); + return this.loadMcpConfigWithGateway(sessionUri); } // Standard path: use the CLIMCPServerEnabled setting @@ -65,7 +64,7 @@ export class CopilotCLIMCPHandler implements ICopilotCLIMCPHandler { if (enabled) { this.logService.info('[CopilotCLIMCPHandler] MCP server forwarding is enabled, using gateway configuration'); - return this.loadMcpConfigWithGateway(); + return this.loadMcpConfigWithGateway(sessionUri); } const processedConfig: Record = {}; @@ -79,11 +78,11 @@ export class CopilotCLIMCPHandler implements ICopilotCLIMCPHandler { /** * Use the Gateway to handle all connections */ - private async loadMcpConfigWithGateway(): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }> { + private async loadMcpConfigWithGateway(sessionUri: URI): Promise<{ mcpConfig: Record | undefined; disposable: IDisposable }> { const mcpConfig: Record = {}; const disposable = new DisposableStore(); try { - const gateway = await this.mcpService.startMcpGateway(URI.from({ scheme: 'copilot-cli', path: `mcp-gateway-${generateUuid()}` })); + const gateway = await this.mcpService.startMcpGateway(sessionUri); if (gateway) { disposable.add(gateway); for (const server of gateway.servers) { diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/testHelpers.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/testHelpers.ts index efe724f0c1e52..d90cb1bf6fcee 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/testHelpers.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/testHelpers.ts @@ -103,7 +103,7 @@ export class NullICopilotCLIImageSupport implements ICopilotCLIImageSupport { export class NullCopilotCLIMCPHandler implements ICopilotCLIMCPHandler { _serviceBrand: undefined; - async loadMcpConfig(): Promise<{ mcpConfig: Record[string]> | undefined; disposable: IDisposable }> { + async loadMcpConfig(_resource: URI): Promise<{ mcpConfig: Record[string]> | undefined; disposable: IDisposable }> { return { mcpConfig: undefined, disposable: Disposable.None }; } }