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