Path: blob/main/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CancellationToken } from '../../../../base/common/cancellation.js';6import { Codicon } from '../../../../base/common/codicons.js';7import { CancellationError } from '../../../../base/common/errors.js';8import { Disposable, MutableDisposable } from '../../../../base/common/lifecycle.js';9import { autorun, observableValue } from '../../../../base/common/observable.js';10import { localize } from '../../../../nls.js';11import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';12import { IWorkbenchContribution } from '../../../common/contributions.js';13import { ChatContextPick, IChatContextPickService } from '../../chat/browser/chatContextPickService.js';14import { McpResourcePickHelper } from './mcpResourceQuickAccess.js';1516export class McpAddContextContribution extends Disposable implements IWorkbenchContribution {17private readonly _helper: McpResourcePickHelper;18private readonly _addContextMenu = this._register(new MutableDisposable());19constructor(20@IChatContextPickService private readonly _chatContextPickService: IChatContextPickService,21@IInstantiationService instantiationService: IInstantiationService,22) {23super();2425this._helper = instantiationService.createInstance(McpResourcePickHelper);26this._register(autorun(reader => {27const enabled = this._helper.hasServersWithResources.read(reader);28if (enabled && !this._addContextMenu.value) {29this._registerAddContextMenu();30} else {31this._addContextMenu.clear();32}33}));34}3536private _registerAddContextMenu() {37this._addContextMenu.value = this._chatContextPickService.registerChatContextItem({38type: 'pickerPick',39label: localize('mcp.addContext', "MCP Resources..."),40icon: Codicon.mcp,41asPicker: () => ({42placeholder: localize('mcp.addContext.placeholder', "Select MCP Resource..."),43picks: (_query, token) => this._getResourcePicks(token),44}),45});46}4748private _getResourcePicks(token: CancellationToken) {49const observable = observableValue<{ busy: boolean; picks: ChatContextPick[] }>(this, { busy: true, picks: [] });5051this._helper.getPicks(servers => {52const picks: ChatContextPick[] = [];53for (const [server, resources] of servers) {54if (resources.length === 0) {55continue;56}5758picks.push(McpResourcePickHelper.sep(server));59for (const resource of resources) {60picks.push({61...McpResourcePickHelper.item(resource),62asAttachment: () => this._helper.toAttachment(resource).then(r => {63if (!r) {64throw new CancellationError();65} else {66return r;67}68}),69});70}71}72observable.set({ picks, busy: true }, undefined);73}, token).finally(() => {74observable.set({ busy: false, picks: observable.get().picks }, undefined);75});7677return observable;78}79}808182