@codingame/monaco-vscode-mcp-service-override 17.2.0 → 18.0.0
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/index.js +20 -2
- package/package.json +14 -5
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +26 -0
- package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +170 -0
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +35 -0
- package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +292 -0
- package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.d.ts +65 -0
- package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.js +9 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +64 -5
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.d.ts +12 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +76 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +73 -27
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +106 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +423 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +61 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +542 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.d.ts +17 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +45 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +54 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +272 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.d.ts +24 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +193 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +56 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +176 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.d.ts +3 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.js +27 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +8 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +6 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +4 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.js +4 -4
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.d.ts +23 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.js +89 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.service.d.ts +6 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.service.js +6 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +8 -6
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +30 -47
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.d.ts +35 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.js +206 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.d.ts +26 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +110 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +38 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +256 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +29 -13
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +313 -116
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.d.ts +2 -2
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +15 -17
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +16 -7
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +58 -39
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.d.ts +1 -1
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +109 -46
- package/vscode/src/vs/workbench/contrib/mcp/common/uriTemplate.d.ts +25 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/uriTemplate.js +296 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.d.ts +27 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.js +73 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.d.ts +51 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +391 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpUsageService.d.ts +27 -0
- package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpUsageService.js +105 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.d.ts +0 -395
- package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.js +0 -14
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
-
import { Sequencer,
|
|
4
|
-
import {
|
|
3
|
+
import { raceCancellationError, Sequencer, AsyncIterableObject } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
4
|
+
import { CancellationToken, CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
5
5
|
import { parseTree, findNodeAtOffset, getNodePath } from '@codingame/monaco-vscode-api/vscode/vs/base/common/json';
|
|
6
6
|
import { Disposable, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
7
7
|
import { LRUCache } from '@codingame/monaco-vscode-api/vscode/vs/base/common/map';
|
|
8
|
+
import { mapValues } from '@codingame/monaco-vscode-api/vscode/vs/base/common/objects';
|
|
8
9
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
9
10
|
import { basename } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
|
|
10
11
|
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
|
|
@@ -23,16 +24,21 @@ import { IWorkspaceContextService } from '@codingame/monaco-vscode-api/vscode/vs
|
|
|
23
24
|
import { IEditorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService.service';
|
|
24
25
|
import { IExtensionService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensions.service';
|
|
25
26
|
import { IOutputService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/output/common/output.service';
|
|
26
|
-
import { mcpActivationEvent } from '@codingame/monaco-vscode-
|
|
27
|
+
import { mcpActivationEvent } from '@codingame/monaco-vscode-aa9ead53-dfd3-59da-b9e7-f163d201de8d-common/vscode/vs/workbench/contrib/mcp/common/mcpConfiguration';
|
|
28
|
+
import { McpDevModeServerAttache } from './mcpDevMode.js';
|
|
27
29
|
import { IMcpRegistry } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes.service';
|
|
28
|
-
import { McpConnectionState,
|
|
30
|
+
import { McpConnectionState, McpConnectionFailedError, McpServerCacheState, extensionMcpCollectionPrefix, McpServerTransportType, mcpPromptReplaceSpecialChars, McpCapability, McpToolName, McpResourceURI } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
|
|
31
|
+
import { IMcpSamplingService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service';
|
|
32
|
+
import { UriTemplate } from './uriTemplate.js';
|
|
29
33
|
import Severity from '@codingame/monaco-vscode-api/vscode/vs/base/common/severity';
|
|
30
|
-
import {
|
|
31
|
-
import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/derived';
|
|
32
|
-
import { observableFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
34
|
+
import { observableValue, disposableObservableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
|
|
35
|
+
import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
|
|
36
|
+
import { observableFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableFromEvent';
|
|
37
|
+
import { autorun, autorunWithStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
|
|
38
|
+
import { transaction } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/transaction';
|
|
39
|
+
import { ObservablePromise } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/promise';
|
|
35
40
|
|
|
41
|
+
var McpServer_1;
|
|
36
42
|
const toolInvalidCharRe = /[^a-z0-9_-]/gi;
|
|
37
43
|
let McpServerMetadataCache = class McpServerMetadataCache extends Disposable {
|
|
38
44
|
constructor(scope, storageService) {
|
|
@@ -63,11 +69,11 @@ let McpServerMetadataCache = class McpServerMetadataCache extends Disposable {
|
|
|
63
69
|
this.extensionServers.clear();
|
|
64
70
|
this.didChange = true;
|
|
65
71
|
}
|
|
66
|
-
|
|
72
|
+
get(definitionId) {
|
|
67
73
|
return this.cache.get(definitionId);
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
this.cache.set(definitionId,
|
|
75
|
+
store(definitionId, entry) {
|
|
76
|
+
this.cache.set(definitionId, entry);
|
|
71
77
|
this.didChange = true;
|
|
72
78
|
}
|
|
73
79
|
getServers(collectionId) {
|
|
@@ -86,19 +92,75 @@ let McpServerMetadataCache = class McpServerMetadataCache extends Disposable {
|
|
|
86
92
|
McpServerMetadataCache = ( __decorate([
|
|
87
93
|
( __param(1, IStorageService))
|
|
88
94
|
], McpServerMetadataCache));
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
class CachedPrimitive {
|
|
96
|
+
constructor(_definitionId, _cache, _fromCache, _toT) {
|
|
97
|
+
this._definitionId = _definitionId;
|
|
98
|
+
this._cache = _cache;
|
|
99
|
+
this._fromCache = _fromCache;
|
|
100
|
+
this._toT = _toT;
|
|
101
|
+
this.fromServerPromise = observableValue(this, undefined);
|
|
102
|
+
this.fromServer = derived(reader => this.fromServerPromise.read(reader)?.promiseResult.read(reader)?.data);
|
|
103
|
+
this.value = derived(reader => {
|
|
104
|
+
const serverTools = this.fromServer.read(reader);
|
|
105
|
+
const definitions = serverTools?.data ?? this.fromCache?.data ?? [];
|
|
106
|
+
return this._toT(definitions, reader);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
get fromCache() {
|
|
110
|
+
const c = this._cache.get(this._definitionId);
|
|
111
|
+
return c ? { data: this._fromCache(c), nonce: c.nonce } : undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
let McpServer = McpServer_1 = class McpServer extends Disposable {
|
|
115
|
+
static async callOn(server, fn, token = CancellationToken.None) {
|
|
116
|
+
await server.start();
|
|
117
|
+
let ranOnce = false;
|
|
118
|
+
let d;
|
|
119
|
+
const callPromise = ( new Promise((resolve, reject) => {
|
|
120
|
+
d = autorun(reader => {
|
|
121
|
+
const connection = server.connection.read(reader);
|
|
122
|
+
if (!connection || ranOnce) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const handler = connection.handler.read(reader);
|
|
126
|
+
if (!handler) {
|
|
127
|
+
const state = connection.state.read(reader);
|
|
128
|
+
if (state.state === McpConnectionState.Kind.Error) {
|
|
129
|
+
reject(( new McpConnectionFailedError(`MCP server could not be started: ${state.message}`)));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
else if (state.state === McpConnectionState.Kind.Stopped) {
|
|
133
|
+
reject(( new McpConnectionFailedError('MCP server has stopped')));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
resolve(fn(handler));
|
|
141
|
+
ranOnce = true;
|
|
142
|
+
});
|
|
143
|
+
}));
|
|
144
|
+
return raceCancellationError(callPromise, token).finally(() => d.dispose());
|
|
145
|
+
}
|
|
146
|
+
get capabilities() {
|
|
147
|
+
return this._capabilities;
|
|
148
|
+
}
|
|
149
|
+
get tools() {
|
|
150
|
+
return this._tools.value;
|
|
151
|
+
}
|
|
152
|
+
get prompts() {
|
|
153
|
+
return this._prompts.value;
|
|
92
154
|
}
|
|
93
155
|
get trusted() {
|
|
94
156
|
return this._mcpRegistry.getTrust(this.collection);
|
|
95
157
|
}
|
|
96
|
-
constructor(collection, definition, explicitRoots, _requiresExtensionActivation,
|
|
158
|
+
constructor(collection, definition, explicitRoots, _requiresExtensionActivation, _primitiveCache, toolPrefix, _mcpRegistry, workspacesService, _extensionService, _loggerService, _outputService, _telemetryService, _commandService, _instantiationService, _notificationService, _openerService, _samplingService) {
|
|
97
159
|
super();
|
|
98
160
|
this.collection = collection;
|
|
99
161
|
this.definition = definition;
|
|
100
162
|
this._requiresExtensionActivation = _requiresExtensionActivation;
|
|
101
|
-
this.
|
|
163
|
+
this._primitiveCache = _primitiveCache;
|
|
102
164
|
this._mcpRegistry = _mcpRegistry;
|
|
103
165
|
this._extensionService = _extensionService;
|
|
104
166
|
this._loggerService = _loggerService;
|
|
@@ -108,41 +170,42 @@ let McpServer = class McpServer extends Disposable {
|
|
|
108
170
|
this._instantiationService = _instantiationService;
|
|
109
171
|
this._notificationService = _notificationService;
|
|
110
172
|
this._openerService = _openerService;
|
|
173
|
+
this._samplingService = _samplingService;
|
|
111
174
|
this._connectionSequencer = ( new Sequencer());
|
|
112
175
|
this._connection = this._register(disposableObservableValue(this, undefined));
|
|
113
176
|
this.connection = this._connection;
|
|
114
177
|
this.connectionState = derived(reader => this._connection.read(reader)?.state.read(reader) ?? { state: McpConnectionState.Kind.Stopped });
|
|
115
|
-
this.
|
|
116
|
-
this.
|
|
117
|
-
|
|
118
|
-
const currentNonce = () => this._mcpRegistry.collections.read(reader)
|
|
119
|
-
.find(c => c.id === this.collection.id)
|
|
120
|
-
?.serverDefinitions.read(reader)
|
|
121
|
-
.find(d => d.id === this.definition.id)
|
|
122
|
-
?.cacheNonce;
|
|
178
|
+
this._capabilities = observableValue('mcpserver.capabilities', undefined);
|
|
179
|
+
this.cacheState = derived(reader => {
|
|
180
|
+
const currentNonce = () => this._fullDefinitions.read(reader)?.server?.cacheNonce;
|
|
123
181
|
const stateWhenServingFromCache = () => {
|
|
124
|
-
if (!this.
|
|
125
|
-
return
|
|
182
|
+
if (!this._tools.fromCache) {
|
|
183
|
+
return McpServerCacheState.Unknown;
|
|
126
184
|
}
|
|
127
|
-
return currentNonce() === this.
|
|
185
|
+
return currentNonce() === this._tools.fromCache.nonce ? McpServerCacheState.Cached : McpServerCacheState.Outdated;
|
|
128
186
|
};
|
|
129
|
-
const fromServer = this.
|
|
187
|
+
const fromServer = this._tools.fromServerPromise.read(reader);
|
|
130
188
|
const connectionState = this.connectionState.read(reader);
|
|
131
|
-
const isIdle = McpConnectionState.canBeStarted(connectionState.state)
|
|
189
|
+
const isIdle = McpConnectionState.canBeStarted(connectionState.state) || !fromServer;
|
|
132
190
|
if (isIdle) {
|
|
133
191
|
return stateWhenServingFromCache();
|
|
134
192
|
}
|
|
135
193
|
const fromServerResult = fromServer?.promiseResult.read(reader);
|
|
136
194
|
if (!fromServerResult) {
|
|
137
|
-
return this.
|
|
195
|
+
return this._tools.fromCache ? McpServerCacheState.RefreshingFromCached : McpServerCacheState.RefreshingFromUnknown;
|
|
138
196
|
}
|
|
139
197
|
if (fromServerResult.error) {
|
|
140
198
|
return stateWhenServingFromCache();
|
|
141
199
|
}
|
|
142
|
-
return fromServerResult.data?.nonce === currentNonce() ?
|
|
200
|
+
return fromServerResult.data?.nonce === currentNonce() ? McpServerCacheState.Live : McpServerCacheState.Outdated;
|
|
143
201
|
});
|
|
202
|
+
this._lastModeDebugged = false;
|
|
203
|
+
this.runningToolCalls = 0;
|
|
204
|
+
this._fullDefinitions = this._mcpRegistry.getServerDefinition(this.collection, this.definition);
|
|
144
205
|
this._loggerId = `mcpServer.${definition.id}`;
|
|
145
206
|
this._logger = this._register(_loggerService.createLogger(this._loggerId, { hidden: true, name: `MCP: ${definition.label}` }));
|
|
207
|
+
const that = this;
|
|
208
|
+
this._register(this._instantiationService.createInstance(McpDevModeServerAttache, this, { get lastModeDebugged() { return that._lastModeDebugged; } }));
|
|
146
209
|
this._register(toDisposable(() => _loggerService.deregisterLogger(this._loggerId)));
|
|
147
210
|
const workspaces = explicitRoots
|
|
148
211
|
? observableValue(this, ( explicitRoots.map(uri => ({ uri, name: basename(uri) }))))
|
|
@@ -163,28 +226,56 @@ let McpServer = class McpServer extends Disposable {
|
|
|
163
226
|
if (handler) {
|
|
164
227
|
this.populateLiveData(handler, cnx?.definition.cacheNonce, store);
|
|
165
228
|
}
|
|
166
|
-
else {
|
|
229
|
+
else if (this._tools) {
|
|
167
230
|
this.resetLiveData();
|
|
168
231
|
}
|
|
169
232
|
}));
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
233
|
+
this._tools = ( new CachedPrimitive(
|
|
234
|
+
this.definition.id,
|
|
235
|
+
this._primitiveCache,
|
|
236
|
+
(entry) => entry.tools,
|
|
237
|
+
(entry) => ( entry.map(def => ( new McpTool(this, toolPrefix, def)))).sort((a, b) => a.compare(b))
|
|
238
|
+
));
|
|
239
|
+
this._prompts = ( new CachedPrimitive(
|
|
240
|
+
this.definition.id,
|
|
241
|
+
this._primitiveCache,
|
|
242
|
+
(entry) => entry.prompts || [],
|
|
243
|
+
(entry) => ( entry.map(e => ( new McpPrompt(this, e))))
|
|
244
|
+
));
|
|
245
|
+
this._capabilities.set(this._primitiveCache.get(this.definition.id)?.capabilities, undefined);
|
|
246
|
+
}
|
|
247
|
+
readDefinitions() {
|
|
248
|
+
return this._fullDefinitions;
|
|
177
249
|
}
|
|
178
250
|
showOutput() {
|
|
179
251
|
this._loggerService.setVisibility(this._loggerId, true);
|
|
180
252
|
this._outputService.showChannel(this._loggerId);
|
|
181
253
|
}
|
|
182
|
-
|
|
254
|
+
resources(token) {
|
|
255
|
+
const cts = ( new CancellationTokenSource(token));
|
|
256
|
+
return ( new AsyncIterableObject(async (emitter) => {
|
|
257
|
+
await McpServer_1.callOn(this, async (handler) => {
|
|
258
|
+
for await (const resource of handler.listResourcesIterable({}, cts.token)) {
|
|
259
|
+
emitter.emitOne(( resource.map(r => ( new McpResource(this, r)))));
|
|
260
|
+
if (cts.token.isCancellationRequested) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}, () => cts.dispose(true)));
|
|
266
|
+
}
|
|
267
|
+
resourceTemplates(token) {
|
|
268
|
+
return McpServer_1.callOn(this, async (handler) => {
|
|
269
|
+
const templates = await handler.listResourceTemplates({}, token);
|
|
270
|
+
return ( templates.map(t => ( new McpResourceTemplate(this, t))));
|
|
271
|
+
}, token);
|
|
272
|
+
}
|
|
273
|
+
start({ isFromInteraction, debug } = {}) {
|
|
183
274
|
return this._connectionSequencer.queue(async () => {
|
|
184
275
|
const activationEvent = mcpActivationEvent(this.collection.id.slice(extensionMcpCollectionPrefix.length));
|
|
185
276
|
if (this._requiresExtensionActivation && !this._extensionService.activationEventIsDone(activationEvent)) {
|
|
186
277
|
await this._extensionService.activateByEvent(activationEvent);
|
|
187
|
-
await Promise.all(( this._mcpRegistry.delegates
|
|
278
|
+
await Promise.all(( this._mcpRegistry.delegates.get()
|
|
188
279
|
.map(r => r.waitForInitialProviderPromises())));
|
|
189
280
|
if (this._store.isDisposed) {
|
|
190
281
|
return { state: McpConnectionState.Kind.Stopped };
|
|
@@ -197,11 +288,13 @@ let McpServer = class McpServer extends Disposable {
|
|
|
197
288
|
this._connection.set(connection, undefined);
|
|
198
289
|
}
|
|
199
290
|
if (!connection) {
|
|
291
|
+
this._lastModeDebugged = !!debug;
|
|
200
292
|
connection = await this._mcpRegistry.resolveConnection({
|
|
201
293
|
logger: this._logger,
|
|
202
294
|
collectionRef: this.collection,
|
|
203
295
|
definitionRef: this.definition,
|
|
204
296
|
forceTrust: isFromInteraction,
|
|
297
|
+
debug,
|
|
205
298
|
});
|
|
206
299
|
if (!connection) {
|
|
207
300
|
return { state: McpConnectionState.Kind.Stopped };
|
|
@@ -212,19 +305,28 @@ let McpServer = class McpServer extends Disposable {
|
|
|
212
305
|
}
|
|
213
306
|
this._connection.set(connection, undefined);
|
|
214
307
|
}
|
|
308
|
+
if (isFromInteraction && connection.definition.devMode) {
|
|
309
|
+
this.showOutput();
|
|
310
|
+
}
|
|
215
311
|
const start = Date.now();
|
|
216
|
-
const state = await connection.start(
|
|
312
|
+
const state = await connection.start({
|
|
313
|
+
createMessageRequestHandler: params => this._samplingService.sample({
|
|
314
|
+
isDuringToolCall: true,
|
|
315
|
+
server: this,
|
|
316
|
+
params,
|
|
317
|
+
}).then(r => r.sample)
|
|
318
|
+
});
|
|
217
319
|
this._telemetryService.publicLog2('mcp/serverBootState', {
|
|
218
320
|
state: McpConnectionState.toKindString(state.state),
|
|
219
321
|
time: Date.now() - start,
|
|
220
322
|
});
|
|
221
323
|
if (state.state === McpConnectionState.Kind.Error && isFromInteraction) {
|
|
222
|
-
this.showInteractiveError(connection, state);
|
|
324
|
+
this.showInteractiveError(connection, state, debug);
|
|
223
325
|
}
|
|
224
326
|
return state;
|
|
225
327
|
});
|
|
226
328
|
}
|
|
227
|
-
showInteractiveError(cnx, error) {
|
|
329
|
+
showInteractiveError(cnx, error, debug) {
|
|
228
330
|
if (error.code === 'ENOENT' && cnx.launchDefinition.type === McpServerTransportType.Stdio) {
|
|
229
331
|
let docsLink;
|
|
230
332
|
switch (cnx.launchDefinition.command) {
|
|
@@ -236,17 +338,29 @@ let McpServer = class McpServer extends Disposable {
|
|
|
236
338
|
break;
|
|
237
339
|
}
|
|
238
340
|
const options = [{
|
|
239
|
-
label: ( localize(
|
|
341
|
+
label: ( localize(7968, "Show Output")),
|
|
240
342
|
run: () => this.showOutput(),
|
|
241
343
|
}];
|
|
344
|
+
if (cnx.definition.devMode?.debug?.type === 'debugpy' && debug) {
|
|
345
|
+
this._notificationService.prompt(Severity.Error, ( localize(
|
|
346
|
+
7969,
|
|
347
|
+
'The command "{0}" was not found. You can specify the path to debugpy in the `dev.debug.debugpyPath` option.',
|
|
348
|
+
cnx.launchDefinition.command,
|
|
349
|
+
cnx.definition.label
|
|
350
|
+
)), [...options, {
|
|
351
|
+
label: ( localize(7970, 'View Docs')),
|
|
352
|
+
run: () => this._openerService.open(( URI.parse('https://aka.ms/vscode-mcp-install/debugpy'))),
|
|
353
|
+
}]);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
242
356
|
if (docsLink) {
|
|
243
357
|
options.push({
|
|
244
|
-
label: ( localize(
|
|
358
|
+
label: ( localize(7971, 'Install {0}', cnx.launchDefinition.command)),
|
|
245
359
|
run: () => this._openerService.open(( URI.parse(docsLink))),
|
|
246
360
|
});
|
|
247
361
|
}
|
|
248
362
|
this._notificationService.prompt(Severity.Error, ( localize(
|
|
249
|
-
|
|
363
|
+
7972,
|
|
250
364
|
'The command "{0}" needed to run {1} was not found.',
|
|
251
365
|
cnx.launchDefinition.command,
|
|
252
366
|
cnx.definition.label
|
|
@@ -254,7 +368,7 @@ let McpServer = class McpServer extends Disposable {
|
|
|
254
368
|
}
|
|
255
369
|
else {
|
|
256
370
|
this._notificationService.warn(( localize(
|
|
257
|
-
|
|
371
|
+
7973,
|
|
258
372
|
'The MCP server {0} could not be started: {1}',
|
|
259
373
|
cnx.definition.label,
|
|
260
374
|
error.message
|
|
@@ -266,7 +380,8 @@ let McpServer = class McpServer extends Disposable {
|
|
|
266
380
|
}
|
|
267
381
|
resetLiveData() {
|
|
268
382
|
transaction(tx => {
|
|
269
|
-
this.
|
|
383
|
+
this._tools.fromServerPromise.set(undefined, tx);
|
|
384
|
+
this._prompts.fromServerPromise.set(undefined, tx);
|
|
270
385
|
});
|
|
271
386
|
}
|
|
272
387
|
async _normalizeTool(originalTool) {
|
|
@@ -304,7 +419,7 @@ let McpServer = class McpServer extends Disposable {
|
|
|
304
419
|
const validated = [];
|
|
305
420
|
for (const [i, result] of validations.entries()) {
|
|
306
421
|
if ('error' in result) {
|
|
307
|
-
error += ( localize(
|
|
422
|
+
error += ( localize(7974, 'Tool `{0}` has invalid JSON parameters:', tools[i].name)) + '\n';
|
|
308
423
|
for (const message of result.error) {
|
|
309
424
|
error += `\t- ${message}\n`;
|
|
310
425
|
}
|
|
@@ -327,93 +442,143 @@ let McpServer = class McpServer extends Disposable {
|
|
|
327
442
|
const toolPromise = handler.capabilities.tools ? handler.listTools({}, cts.token) : Promise.resolve([]);
|
|
328
443
|
const toolPromiseSafe = toolPromise.then(async (tools) => {
|
|
329
444
|
handler.logger.info(`Discovered ${tools.length} tools`);
|
|
330
|
-
return {
|
|
445
|
+
return { data: await this._getValidatedTools(handler, tools), nonce: cacheNonce };
|
|
331
446
|
});
|
|
332
|
-
this.
|
|
333
|
-
return
|
|
447
|
+
this._tools.fromServerPromise.set(( new ObservablePromise(toolPromiseSafe)), tx);
|
|
448
|
+
return toolPromiseSafe;
|
|
449
|
+
};
|
|
450
|
+
const updatePrompts = (tx) => {
|
|
451
|
+
const promptsPromise = handler.capabilities.prompts ? handler.listPrompts({}, cts.token) : Promise.resolve([]);
|
|
452
|
+
const promptsPromiseSafe = promptsPromise.then(data => ({ data, nonce: cacheNonce }));
|
|
453
|
+
this._prompts.fromServerPromise.set(( new ObservablePromise(promptsPromiseSafe)), tx);
|
|
454
|
+
return promptsPromiseSafe;
|
|
334
455
|
};
|
|
335
456
|
store.add(handler.onDidChangeToolList(() => {
|
|
336
457
|
handler.logger.info('Tool list changed, refreshing tools...');
|
|
337
458
|
updateTools(undefined);
|
|
338
459
|
}));
|
|
339
|
-
|
|
460
|
+
store.add(handler.onDidChangePromptList(() => {
|
|
461
|
+
handler.logger.info('Prompts list changed, refreshing prompts...');
|
|
462
|
+
updatePrompts(undefined);
|
|
463
|
+
}));
|
|
340
464
|
transaction(tx => {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
465
|
+
const capabilities = encodeCapabilities(handler.capabilities);
|
|
466
|
+
this._capabilities.set(capabilities, tx);
|
|
467
|
+
Promise.all([updateTools(tx), updatePrompts(tx)]).then(([{ data: tools }, { data: prompts }]) => {
|
|
468
|
+
this._primitiveCache.store(this.definition.id, {
|
|
469
|
+
nonce: cacheNonce,
|
|
470
|
+
tools,
|
|
471
|
+
prompts,
|
|
472
|
+
capabilities,
|
|
473
|
+
});
|
|
474
|
+
this._telemetryService.publicLog2('mcp/serverBoot', {
|
|
475
|
+
supportsLogging: !!handler.capabilities.logging,
|
|
476
|
+
supportsPrompts: !!handler.capabilities.prompts,
|
|
477
|
+
supportsResources: !!handler.capabilities.resources,
|
|
478
|
+
toolCount: tools.length,
|
|
479
|
+
serverName: handler.serverInfo.name,
|
|
480
|
+
serverVersion: handler.serverInfo.version,
|
|
481
|
+
});
|
|
352
482
|
});
|
|
353
483
|
});
|
|
354
484
|
}
|
|
355
|
-
async callOn(fn, token = CancellationToken.None) {
|
|
356
|
-
await this.start();
|
|
357
|
-
let ranOnce = false;
|
|
358
|
-
let d;
|
|
359
|
-
const callPromise = ( new Promise((resolve, reject) => {
|
|
360
|
-
d = autorun(reader => {
|
|
361
|
-
const connection = this._connection.read(reader);
|
|
362
|
-
if (!connection || ranOnce) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const handler = connection.handler.read(reader);
|
|
366
|
-
if (!handler) {
|
|
367
|
-
const state = connection.state.read(reader);
|
|
368
|
-
if (state.state === McpConnectionState.Kind.Error) {
|
|
369
|
-
reject(( new McpConnectionFailedError(`MCP server could not be started: ${state.message}`)));
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
else if (state.state === McpConnectionState.Kind.Stopped) {
|
|
373
|
-
reject(( new McpConnectionFailedError('MCP server has stopped')));
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
resolve(fn(handler));
|
|
381
|
-
ranOnce = true;
|
|
382
|
-
});
|
|
383
|
-
}));
|
|
384
|
-
return raceCancellationError(callPromise, token).finally(() => d.dispose());
|
|
385
|
-
}
|
|
386
485
|
};
|
|
387
|
-
McpServer = ( __decorate([
|
|
388
|
-
( __param(
|
|
389
|
-
( __param(
|
|
390
|
-
( __param(
|
|
391
|
-
( __param(
|
|
392
|
-
( __param(
|
|
393
|
-
( __param(
|
|
394
|
-
( __param(
|
|
395
|
-
( __param(
|
|
396
|
-
( __param(
|
|
397
|
-
( __param(
|
|
486
|
+
McpServer = McpServer_1 = ( __decorate([
|
|
487
|
+
( __param(6, IMcpRegistry)),
|
|
488
|
+
( __param(7, IWorkspaceContextService)),
|
|
489
|
+
( __param(8, IExtensionService)),
|
|
490
|
+
( __param(9, ILoggerService)),
|
|
491
|
+
( __param(10, IOutputService)),
|
|
492
|
+
( __param(11, ITelemetryService)),
|
|
493
|
+
( __param(12, ICommandService)),
|
|
494
|
+
( __param(13, IInstantiationService)),
|
|
495
|
+
( __param(14, INotificationService)),
|
|
496
|
+
( __param(15, IOpenerService)),
|
|
497
|
+
( __param(16, IMcpSamplingService))
|
|
398
498
|
], McpServer));
|
|
499
|
+
class McpPrompt {
|
|
500
|
+
constructor(_server, _definition) {
|
|
501
|
+
this._server = _server;
|
|
502
|
+
this._definition = _definition;
|
|
503
|
+
this.id = mcpPromptReplaceSpecialChars(this._server.definition.label + '.' + _definition.name);
|
|
504
|
+
this.name = _definition.name;
|
|
505
|
+
this.description = _definition.description;
|
|
506
|
+
this.arguments = _definition.arguments || [];
|
|
507
|
+
}
|
|
508
|
+
async resolve(args, token) {
|
|
509
|
+
const result = await McpServer.callOn(this._server, h => h.getPrompt({ name: this._definition.name, arguments: args }, token), token);
|
|
510
|
+
return result.messages;
|
|
511
|
+
}
|
|
512
|
+
async complete(argument, prefix, token) {
|
|
513
|
+
const result = await McpServer.callOn(this._server, h => h.complete({
|
|
514
|
+
ref: { type: 'ref/prompt', name: this._definition.name },
|
|
515
|
+
argument: { name: argument, value: prefix, }
|
|
516
|
+
}, token), token);
|
|
517
|
+
return result.completion.values;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
function encodeCapabilities(cap) {
|
|
521
|
+
let out = 0;
|
|
522
|
+
if (cap.logging) {
|
|
523
|
+
out |= McpCapability.Logging;
|
|
524
|
+
}
|
|
525
|
+
if (cap.completions) {
|
|
526
|
+
out |= McpCapability.Completions;
|
|
527
|
+
}
|
|
528
|
+
if (cap.prompts) {
|
|
529
|
+
out |= McpCapability.Prompts;
|
|
530
|
+
if (cap.prompts.listChanged) {
|
|
531
|
+
out |= McpCapability.PromptsListChanged;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (cap.resources) {
|
|
535
|
+
out |= McpCapability.Resources;
|
|
536
|
+
if (cap.resources.subscribe) {
|
|
537
|
+
out |= McpCapability.ResourcesSubscribe;
|
|
538
|
+
}
|
|
539
|
+
if (cap.resources.listChanged) {
|
|
540
|
+
out |= McpCapability.ResourcesListChanged;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
if (cap.tools) {
|
|
544
|
+
out |= McpCapability.Tools;
|
|
545
|
+
if (cap.tools.listChanged) {
|
|
546
|
+
out |= McpCapability.ToolsListChanged;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return out;
|
|
550
|
+
}
|
|
399
551
|
class McpTool {
|
|
400
552
|
get definition() { return this._definition; }
|
|
401
553
|
constructor(_server, idPrefix, _definition) {
|
|
402
554
|
this._server = _server;
|
|
403
555
|
this._definition = _definition;
|
|
404
|
-
this.
|
|
556
|
+
this.referenceName = _definition.name.replaceAll('.', '_');
|
|
557
|
+
this.id = (idPrefix + _definition.name).replaceAll('.', '_').slice(0, McpToolName.MaxLength);
|
|
405
558
|
}
|
|
406
|
-
call(params, token) {
|
|
559
|
+
async call(params, token) {
|
|
407
560
|
const name = this._definition.serverToolName ?? this._definition.name;
|
|
408
|
-
|
|
561
|
+
this._server.runningToolCalls++;
|
|
562
|
+
try {
|
|
563
|
+
return await McpServer.callOn(this._server, h => h.callTool({ name, arguments: params }, token), token);
|
|
564
|
+
}
|
|
565
|
+
finally {
|
|
566
|
+
this._server.runningToolCalls--;
|
|
567
|
+
}
|
|
409
568
|
}
|
|
410
|
-
callWithProgress(params, progress, token) {
|
|
411
|
-
|
|
569
|
+
async callWithProgress(params, progress, token) {
|
|
570
|
+
this._server.runningToolCalls++;
|
|
571
|
+
try {
|
|
572
|
+
return await this._callWithProgress(params, progress, token);
|
|
573
|
+
}
|
|
574
|
+
finally {
|
|
575
|
+
this._server.runningToolCalls--;
|
|
576
|
+
}
|
|
412
577
|
}
|
|
413
578
|
_callWithProgress(params, progress, token, allowRetry = true) {
|
|
414
579
|
const name = this._definition.serverToolName ?? this._definition.name;
|
|
415
580
|
const progressToken = generateUuid();
|
|
416
|
-
return this._server
|
|
581
|
+
return McpServer.callOn(this._server, h => {
|
|
417
582
|
let lastProgressN = 0;
|
|
418
583
|
const listener = h.onDidReceiveProgressNotification((e) => {
|
|
419
584
|
if (e.params.progressToken === progressToken) {
|
|
@@ -449,7 +614,7 @@ function warnInvalidTools(instaService, serverName, errorText) {
|
|
|
449
614
|
notificationService.notify({
|
|
450
615
|
severity: Severity.Warning,
|
|
451
616
|
message: ( localize(
|
|
452
|
-
|
|
617
|
+
7975,
|
|
453
618
|
'MCP server `{0}` has tools with invalid parameters which will be omitted.',
|
|
454
619
|
serverName
|
|
455
620
|
)),
|
|
@@ -459,7 +624,7 @@ function warnInvalidTools(instaService, serverName, errorText) {
|
|
|
459
624
|
enabled: true,
|
|
460
625
|
id: 'mcpBadSchema.show',
|
|
461
626
|
tooltip: '',
|
|
462
|
-
label: ( localize(
|
|
627
|
+
label: ( localize(7976, 'Show')),
|
|
463
628
|
run: () => {
|
|
464
629
|
editorService.openEditor({
|
|
465
630
|
resource: undefined,
|
|
@@ -471,5 +636,37 @@ function warnInvalidTools(instaService, serverName, errorText) {
|
|
|
471
636
|
});
|
|
472
637
|
});
|
|
473
638
|
}
|
|
639
|
+
class McpResource {
|
|
640
|
+
constructor(server, original) {
|
|
641
|
+
this.mcpUri = original.uri;
|
|
642
|
+
this.uri = McpResourceURI.fromServer(server.definition, original.uri);
|
|
643
|
+
this.name = original.name;
|
|
644
|
+
this.description = original.description;
|
|
645
|
+
this.mimeType = original.mimeType;
|
|
646
|
+
this.sizeInBytes = original.size;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
class McpResourceTemplate {
|
|
650
|
+
constructor(_server, _definition) {
|
|
651
|
+
this._server = _server;
|
|
652
|
+
this._definition = _definition;
|
|
653
|
+
this.name = _definition.name;
|
|
654
|
+
this.description = _definition.description;
|
|
655
|
+
this.mimeType = _definition.mimeType;
|
|
656
|
+
this.template = UriTemplate.parse(_definition.uriTemplate);
|
|
657
|
+
}
|
|
658
|
+
resolveURI(vars) {
|
|
659
|
+
const serverUri = this.template.resolve(vars);
|
|
660
|
+
return McpResourceURI.fromServer(this._server.definition, serverUri);
|
|
661
|
+
}
|
|
662
|
+
async complete(templatePart, prefix, alreadyResolved, token) {
|
|
663
|
+
const result = await McpServer.callOn(this._server, h => h.complete({
|
|
664
|
+
ref: { type: 'ref/resource', uri: this._definition.uriTemplate },
|
|
665
|
+
argument: { name: templatePart, value: prefix },
|
|
666
|
+
resolved: mapValues(alreadyResolved, v => Array.isArray(v) ? v.join('/') : v),
|
|
667
|
+
}, token), token);
|
|
668
|
+
return result.completion.values;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
474
671
|
|
|
475
672
|
export { McpServer, McpServerMetadataCache, McpTool };
|
|
@@ -4,7 +4,7 @@ import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/pl
|
|
|
4
4
|
import { ILogger } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log";
|
|
5
5
|
import { IMcpHostDelegate } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes";
|
|
6
6
|
import { McpServerRequestHandler } from "./mcpServerRequestHandler.js";
|
|
7
|
-
import { IMcpServerConnection, McpCollectionDefinition, McpConnectionState, McpServerDefinition, McpServerLaunch } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
7
|
+
import { IMcpClientMethods, IMcpServerConnection, McpCollectionDefinition, McpConnectionState, McpServerDefinition, McpServerLaunch } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
8
8
|
export declare class McpServerConnection extends Disposable implements IMcpServerConnection {
|
|
9
9
|
private readonly _collection;
|
|
10
10
|
readonly definition: McpServerDefinition;
|
|
@@ -18,7 +18,7 @@ export declare class McpServerConnection extends Disposable implements IMcpServe
|
|
|
18
18
|
readonly state: IObservable<McpConnectionState>;
|
|
19
19
|
readonly handler: IObservable<McpServerRequestHandler | undefined>;
|
|
20
20
|
constructor(_collection: McpCollectionDefinition, definition: McpServerDefinition, _delegate: IMcpHostDelegate, launchDefinition: McpServerLaunch, _logger: ILogger, _instantiationService: IInstantiationService);
|
|
21
|
-
start(): Promise<McpConnectionState>;
|
|
21
|
+
start(methods: IMcpClientMethods): Promise<McpConnectionState>;
|
|
22
22
|
private adoptLaunch;
|
|
23
23
|
stop(): Promise<void>;
|
|
24
24
|
dispose(): void;
|