@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.
Files changed (64) hide show
  1. package/index.js +20 -2
  2. package/package.json +14 -5
  3. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.d.ts +26 -0
  4. package/vscode/src/vs/platform/mcp/common/mcpGalleryService.js +170 -0
  5. package/vscode/src/vs/platform/mcp/common/mcpManagementService.d.ts +35 -0
  6. package/vscode/src/vs/platform/mcp/common/mcpManagementService.js +292 -0
  7. package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.d.ts +65 -0
  8. package/vscode/src/vs/platform/mcp/common/mcpPlatformTypes.js +9 -0
  9. package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +64 -5
  10. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.d.ts +12 -0
  11. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpAddContextContribution.js +76 -0
  12. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +2 -2
  13. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +73 -27
  14. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.d.ts +106 -0
  15. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerActions.js +423 -0
  16. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.d.ts +61 -0
  17. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditor.js +542 -0
  18. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.d.ts +17 -0
  19. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerEditorInput.js +45 -0
  20. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.d.ts +54 -0
  21. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServerWidgets.js +272 -0
  22. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.d.ts +24 -0
  23. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpServersView.js +193 -0
  24. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.d.ts +56 -0
  25. package/vscode/src/vs/workbench/contrib/mcp/browser/mcpWorkbenchService.js +176 -0
  26. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.d.ts +3 -1
  27. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.js +27 -6
  28. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +8 -6
  29. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +1 -1
  30. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +6 -4
  31. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +1 -1
  32. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +2 -2
  33. package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +4 -2
  34. package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.js +4 -4
  35. package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.d.ts +23 -0
  36. package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.js +89 -0
  37. package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.service.d.ts +6 -0
  38. package/vscode/src/vs/workbench/contrib/mcp/common/mcpDevMode.service.js +6 -0
  39. package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +8 -6
  40. package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +30 -47
  41. package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.d.ts +35 -0
  42. package/vscode/src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.js +206 -0
  43. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.d.ts +26 -0
  44. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingLog.js +110 -0
  45. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.d.ts +38 -0
  46. package/vscode/src/vs/workbench/contrib/mcp/common/mcpSamplingService.js +256 -0
  47. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +29 -13
  48. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +313 -116
  49. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.d.ts +2 -2
  50. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +15 -17
  51. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +16 -7
  52. package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +58 -39
  53. package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.d.ts +1 -1
  54. package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +109 -46
  55. package/vscode/src/vs/workbench/contrib/mcp/common/uriTemplate.d.ts +25 -0
  56. package/vscode/src/vs/workbench/contrib/mcp/common/uriTemplate.js +296 -0
  57. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.d.ts +27 -0
  58. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpAccessService.js +73 -0
  59. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.d.ts +51 -0
  60. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpService.js +391 -0
  61. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpUsageService.d.ts +27 -0
  62. package/vscode/src/vs/workbench/services/authentication/browser/authenticationMcpUsageService.js +105 -0
  63. package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.d.ts +0 -395
  64. package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.js +0 -14
@@ -14,7 +14,7 @@ import { IResolvedValue } from "@codingame/monaco-vscode-api/vscode/vs/workbench
14
14
  import { IEditorService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService.service";
15
15
  import { IMcpHostDelegate, IMcpResolveConnectionOptions } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes";
16
16
  import { IMcpRegistry } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes.service";
17
- import { IMcpServerConnection, LazyCollectionState, McpCollectionDefinition, McpCollectionReference } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
17
+ import { IMcpServerConnection, LazyCollectionState, McpCollectionDefinition, McpCollectionReference, McpDefinitionReference, McpServerDefinition } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
18
18
  export declare class McpRegistry extends Disposable implements IMcpRegistry {
19
19
  private readonly _instantiationService;
20
20
  private readonly _configurationResolverService;
@@ -29,19 +29,21 @@ export declare class McpRegistry extends Disposable implements IMcpRegistry {
29
29
  private readonly _delegates;
30
30
  private readonly _enabled;
31
31
  readonly collections: IObservable<readonly McpCollectionDefinition[]>;
32
- private readonly _collectionToPrefixes;
33
32
  private readonly _workspaceStorage;
34
33
  private readonly _profileStorage;
35
34
  private readonly _trustMemento;
36
35
  private readonly _ongoingLazyActivations;
37
- readonly lazyCollectionState: IObservable<LazyCollectionState>;
38
- get delegates(): readonly IMcpHostDelegate[];
36
+ readonly lazyCollectionState: import("@codingame/monaco-vscode-api/vscode/vs/base/common/observable").IObservableWithChange<LazyCollectionState, void>;
37
+ get delegates(): IObservable<readonly IMcpHostDelegate[]>;
39
38
  private readonly _onDidChangeInputs;
40
39
  readonly onDidChangeInputs: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<void>;
41
40
  constructor(_instantiationService: IInstantiationService, _configurationResolverService: IConfigurationResolverService, _dialogService: IDialogService, _storageService: IStorageService, _productService: IProductService, _notificationService: INotificationService, _editorService: IEditorService, configurationService: IConfigurationService);
42
41
  registerDelegate(delegate: IMcpHostDelegate): IDisposable;
43
42
  registerCollection(collection: McpCollectionDefinition): IDisposable;
44
- collectionToolPrefix(collection: McpCollectionReference): IObservable<string>;
43
+ getServerDefinition(collectionRef: McpDefinitionReference, definitionRef: McpDefinitionReference): IObservable<{
44
+ server: McpServerDefinition | undefined;
45
+ collection: McpCollectionDefinition | undefined;
46
+ }>;
45
47
  discoverCollections(): Promise<McpCollectionDefinition[]>;
46
48
  private _getInputStorage;
47
49
  private _getInputStorageInConfigTarget;
@@ -57,5 +59,5 @@ export declare class McpRegistry extends Disposable implements IMcpRegistry {
57
59
  private _promptForTrustOpenDialog;
58
60
  private _updateStorageWithExpressionInputs;
59
61
  private _replaceVariablesInLaunch;
60
- resolveConnection({ collectionRef, definitionRef, forceTrust, logger }: IMcpResolveConnectionOptions): Promise<IMcpServerConnection | undefined>;
62
+ resolveConnection({ collectionRef, definitionRef, forceTrust, logger, debug }: IMcpResolveConnectionOptions): Promise<IMcpServerConnection | undefined>;
61
63
  }
@@ -2,13 +2,11 @@
2
2
  import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
3
  import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
4
4
  import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
5
- import { StringSHA1 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/hash';
6
5
  import { MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent';
7
6
  import { Lazy } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lazy';
8
7
  import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
9
8
  import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
10
9
  import { basename } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
11
- import { indexOfPattern } from '@codingame/monaco-vscode-api/vscode/vs/base/common/strings';
12
10
  import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
13
11
  import { ConfigurationTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration';
14
12
  import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
@@ -25,19 +23,19 @@ import { IConfigurationResolverService } from '@codingame/monaco-vscode-api/vsco
25
23
  import { ConfigurationResolverExpression } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/configurationResolver/common/configurationResolverExpression';
26
24
  import { AUX_WINDOW_GROUP } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService';
27
25
  import { IEditorService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/editor/common/editorService.service';
28
- import { mcpEnabledSection } from '@codingame/monaco-vscode-1cb11a73-359e-5a2f-9e95-6989cc9858ee-common/vscode/vs/workbench/contrib/mcp/common/mcpConfiguration';
26
+ import { mcpEnabledSection } from '@codingame/monaco-vscode-aa9ead53-dfd3-59da-b9e7-f163d201de8d-common/vscode/vs/workbench/contrib/mcp/common/mcpConfiguration';
27
+ import { IMcpDevModeDebugging } from './mcpDevMode.service.js';
29
28
  import { McpRegistryInputStorage } from './mcpRegistryInputStorage.js';
30
29
  import { McpServerConnection } from './mcpServerConnection.js';
31
30
  import { LazyCollectionState } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
32
31
  import Severity from '@codingame/monaco-vscode-api/vscode/vs/base/common/severity';
33
- import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/base';
34
- import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/derived';
32
+ import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
33
+ import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
35
34
 
36
35
  const createTrustMemento = observableMemento({
37
36
  defaultValue: {},
38
37
  key: 'mcp.trustedCollections'
39
38
  });
40
- const collectionPrefixLen = 3;
41
39
  let McpRegistry = class McpRegistry extends Disposable {
42
40
  get delegates() {
43
41
  return this._delegates;
@@ -53,36 +51,13 @@ let McpRegistry = class McpRegistry extends Disposable {
53
51
  this._editorService = _editorService;
54
52
  this._trustPrompts = ( new Map());
55
53
  this._collections = observableValue('collections', []);
56
- this._delegates = [];
54
+ this._delegates = observableValue('delegates', []);
57
55
  this.collections = derived(reader => {
58
56
  if (!this._enabled.read(reader)) {
59
57
  return [];
60
58
  }
61
59
  return this._collections.read(reader);
62
60
  });
63
- this._collectionToPrefixes = ( this._collections.map(c => {
64
- const hashes = ( c.map((collection) => {
65
- const sha = ( new StringSHA1());
66
- sha.update(collection.id);
67
- const hash = sha.digest();
68
- return { view: indexOfPattern(hash, /[a-z]/i), hash, collection };
69
- }));
70
- const view = (h) => h.hash.slice(h.view, h.view + collectionPrefixLen);
71
- let collided = false;
72
- do {
73
- hashes.sort((a, b) => view(a).localeCompare(view(b)) || a.collection.id.localeCompare(b.collection.id));
74
- collided = false;
75
- for (let i = 1; i < hashes.length; i++) {
76
- const prev = hashes[i - 1];
77
- const curr = hashes[i];
78
- if (view(prev) === view(curr) && curr.view + collectionPrefixLen < curr.hash.length) {
79
- curr.view++;
80
- collided = true;
81
- }
82
- }
83
- } while (collided);
84
- return Object.fromEntries(( hashes.map(h => [h.collection.id, view(h) + '.'])));
85
- }));
86
61
  this._workspaceStorage = ( new Lazy(
87
62
  () => this._register(this._instantiationService.createInstance(McpRegistryInputStorage, StorageScope.WORKSPACE, StorageTarget.USER))
88
63
  ));
@@ -108,14 +83,14 @@ let McpRegistry = class McpRegistry extends Disposable {
108
83
  this._enabled = observableConfigValue(mcpEnabledSection, true, configurationService);
109
84
  }
110
85
  registerDelegate(delegate) {
111
- this._delegates.push(delegate);
112
- this._delegates.sort((a, b) => b.priority - a.priority);
86
+ const delegates = this._delegates.get().slice();
87
+ delegates.push(delegate);
88
+ delegates.sort((a, b) => b.priority - a.priority);
89
+ this._delegates.set(delegates, undefined);
113
90
  return {
114
91
  dispose: () => {
115
- const index = this._delegates.indexOf(delegate);
116
- if (index !== -1) {
117
- this._delegates.splice(index, 1);
118
- }
92
+ const delegates = this._delegates.get().filter(d => d !== delegate);
93
+ this._delegates.set(delegates, undefined);
119
94
  }
120
95
  };
121
96
  }
@@ -126,7 +101,8 @@ let McpRegistry = class McpRegistry extends Disposable {
126
101
  this._collections.set(( currentCollections.map(c => c === toReplace ? collection : c)), undefined);
127
102
  }
128
103
  else {
129
- this._collections.set([...currentCollections, collection], undefined);
104
+ this._collections.set([...currentCollections, collection]
105
+ .sort((a, b) => (a.presentation?.order || 0) - (b.presentation?.order || 0)), undefined);
130
106
  }
131
107
  return {
132
108
  dispose: () => {
@@ -135,8 +111,12 @@ let McpRegistry = class McpRegistry extends Disposable {
135
111
  }
136
112
  };
137
113
  }
138
- collectionToolPrefix(collection) {
139
- return ( this._collectionToPrefixes.map(p => p[collection.id] ?? ''));
114
+ getServerDefinition(collectionRef, definitionRef) {
115
+ const collectionObs = ( this._collections.map(cols => cols.find(c => c.id === collectionRef.id)));
116
+ return ( collectionObs.map((collection, reader) => {
117
+ const server = collection?.serverDefinitions.read(reader).find(s => s.id === definitionRef.id);
118
+ return { collection, server };
119
+ }));
140
120
  }
141
121
  async discoverCollections() {
142
122
  const toDiscover = this._collections.get().filter(c => c.lazy && !c.lazy.isCached);
@@ -221,12 +201,12 @@ let McpRegistry = class McpRegistry extends Disposable {
221
201
  const originURI = collection.presentation?.origin;
222
202
  const labelWithOrigin = originURI ? `[\`${basename(originURI)}\`](${originURI})` : collection.label;
223
203
  const result = await this._dialogService.prompt({
224
- message: ( localize(7737, 'Trust MCP servers from {0}?', collection.label)),
204
+ message: ( localize(7950, 'Trust MCP servers from {0}?', collection.label)),
225
205
  custom: {
226
206
  icon: Codicon.shield,
227
207
  markdownDetails: [{
228
208
  markdown: ( new MarkdownString(( localize(
229
- 7738,
209
+ 7951,
230
210
  '{0} discovered Model Context Protocol servers from {1} (`{2}`). {0} can use their capabilities in Chat.\n\nDo you want to allow running MCP servers from {3}?',
231
211
  this._productService.nameShort,
232
212
  collection.label,
@@ -240,8 +220,8 @@ let McpRegistry = class McpRegistry extends Disposable {
240
220
  }]
241
221
  },
242
222
  buttons: [
243
- { label: ( localize(7739, 'Trust')), run: () => true },
244
- { label: ( localize(7740, 'Do not trust')), run: () => false }
223
+ { label: ( localize(7952, 'Trust')), run: () => true },
224
+ { label: ( localize(7953, 'Do not trust')), run: () => false }
245
225
  ],
246
226
  });
247
227
  return result.result;
@@ -278,7 +258,7 @@ let McpRegistry = class McpRegistry extends Disposable {
278
258
  await this._updateStorageWithExpressionInputs(inputStorage, expr);
279
259
  return await this._configurationResolverService.resolveAsync(folder, expr);
280
260
  }
281
- async resolveConnection({ collectionRef, definitionRef, forceTrust, logger }) {
261
+ async resolveConnection({ collectionRef, definitionRef, forceTrust, logger, debug }) {
282
262
  let collection = this._collections.get().find(c => c.id === collectionRef.id);
283
263
  if (collection?.lazy) {
284
264
  await collection.lazy.load();
@@ -290,7 +270,7 @@ let McpRegistry = class McpRegistry extends Disposable {
290
270
  `Collection or definition not found for ${collectionRef.id} and ${definitionRef.id}`
291
271
  ));
292
272
  }
293
- const delegate = this._delegates.find(d => d.canStart(collection, definition));
273
+ const delegate = this._delegates.get().find(d => d.canStart(collection, definition));
294
274
  if (!delegate) {
295
275
  throw ( new Error('No delegate found that can handle the connection'));
296
276
  }
@@ -320,11 +300,14 @@ let McpRegistry = class McpRegistry extends Disposable {
320
300
  }
321
301
  try {
322
302
  launch = await this._replaceVariablesInLaunch(definition, launch);
303
+ if (definition.devMode && debug) {
304
+ launch = await this._instantiationService.invokeFunction(accessor => accessor.get(IMcpDevModeDebugging).transform(definition, launch));
305
+ }
323
306
  }
324
307
  catch (e) {
325
308
  this._notificationService.notify({
326
309
  severity: Severity.Error,
327
- message: ( localize(7741, 'Error starting {0}: {1}', definition.label, String(e))),
310
+ message: ( localize(7954, 'Error starting {0}: {1}', definition.label, String(e))),
328
311
  actions: {
329
312
  primary: collection.presentation?.origin && [
330
313
  {
@@ -332,7 +315,7 @@ let McpRegistry = class McpRegistry extends Disposable {
332
315
  class: undefined,
333
316
  enabled: true,
334
317
  tooltip: '',
335
- label: ( localize(7742, 'Open Configuration')),
318
+ label: ( localize(7955, 'Open Configuration')),
336
319
  run: () => this._editorService.openEditor({
337
320
  resource: collection.presentation.origin,
338
321
  options: { selection: definition.presentation?.origin?.range }
@@ -0,0 +1,35 @@
1
+ import { CancellationToken } from "@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation";
2
+ import { Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
3
+ import { Disposable, IDisposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
4
+ import { ReadableStreamEvents } from "@codingame/monaco-vscode-api/vscode/vs/base/common/stream";
5
+ import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
6
+ import { FileSystemProviderCapabilities, FileType, IFileChange, IFileDeleteOptions, IFileOverwriteOptions, IFileReadStreamOptions, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileReadStreamCapability, IFileSystemProviderWithFileReadWriteCapability, IFileWriteOptions, IStat, IWatchOptions } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files";
7
+ import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
8
+ import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
9
+ import { IWorkbenchContribution } from "@codingame/monaco-vscode-api/vscode/vs/workbench/common/contributions";
10
+ export declare class McpResourceFilesystem extends Disposable implements IWorkbenchContribution, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileReadStreamCapability {
11
+ private readonly _instantiationService;
12
+ private readonly _fileService;
13
+ private readonly _mcpServiceLazy;
14
+ private get _mcpService();
15
+ readonly onDidChangeCapabilities: Event<any>;
16
+ private readonly _onDidChangeFile;
17
+ readonly onDidChangeFile: Event<readonly IFileChange[]>;
18
+ readonly capabilities: FileSystemProviderCapabilities;
19
+ constructor(_instantiationService: IInstantiationService, _fileService: IFileService);
20
+ readFile(resource: URI): Promise<Uint8Array>;
21
+ readFileStream(resource: URI, opts: IFileReadStreamOptions, token: CancellationToken): ReadableStreamEvents<Uint8Array>;
22
+ watch(uri: URI, _opts: IWatchOptions): IDisposable;
23
+ stat(resource: URI): Promise<IStat>;
24
+ readdir(resource: URI): Promise<[
25
+ string,
26
+ FileType
27
+ ][]>;
28
+ mkdir(resource: URI): Promise<void>;
29
+ writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void>;
30
+ delete(resource: URI, opts: IFileDeleteOptions): Promise<void>;
31
+ rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void>;
32
+ private _readFile;
33
+ private _decodeURI;
34
+ private _readURI;
35
+ }
@@ -0,0 +1,206 @@
1
+
2
+ import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
+ import { sumBy } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
4
+ import { VSBuffer, decodeBase64 } from '@codingame/monaco-vscode-api/vscode/vs/base/common/buffer';
5
+ import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
6
+ import { Event, Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
7
+ import { Lazy } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lazy';
8
+ import { Disposable, DisposableStore, MutableDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
9
+ import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
10
+ import { newWriteableStream } from '@codingame/monaco-vscode-api/vscode/vs/base/common/stream';
11
+ import { equalsIgnoreCase } from '@codingame/monaco-vscode-api/vscode/vs/base/common/strings';
12
+ import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
13
+ import { FileSystemProviderCapabilities, FileChangeType, createFileSystemProviderError, FileSystemProviderErrorCode, FileType } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files';
14
+ import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
15
+ import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
16
+ import { McpServer } from './mcpServer.js';
17
+ import { McpResourceURI, McpCapability } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
18
+ import { IMcpService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service';
19
+ import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
20
+
21
+ let McpResourceFilesystem = class McpResourceFilesystem extends Disposable {
22
+ get _mcpService() {
23
+ return this._mcpServiceLazy.value;
24
+ }
25
+ constructor(_instantiationService, _fileService) {
26
+ super();
27
+ this._instantiationService = _instantiationService;
28
+ this._fileService = _fileService;
29
+ this._mcpServiceLazy = ( new Lazy(() => this._instantiationService.invokeFunction(a => a.get(IMcpService))));
30
+ this.onDidChangeCapabilities = Event.None;
31
+ this._onDidChangeFile = this._register(( new Emitter()));
32
+ this.onDidChangeFile = this._onDidChangeFile.event;
33
+ this.capabilities = FileSystemProviderCapabilities.None
34
+ | FileSystemProviderCapabilities.Readonly
35
+ | FileSystemProviderCapabilities.PathCaseSensitive
36
+ | FileSystemProviderCapabilities.FileReadStream
37
+ | FileSystemProviderCapabilities.FileAtomicRead
38
+ | FileSystemProviderCapabilities.FileReadWrite;
39
+ this._register(this._fileService.registerProvider(McpResourceURI.scheme, this));
40
+ }
41
+ async readFile(resource) {
42
+ return this._readFile(resource);
43
+ }
44
+ readFileStream(resource, opts, token) {
45
+ const stream = newWriteableStream(data => VSBuffer.concat(( data.map(data => VSBuffer.wrap(data)))).buffer);
46
+ this._readFile(resource, token).then(data => {
47
+ if (opts.position) {
48
+ data = data.slice(opts.position);
49
+ }
50
+ if (opts.length) {
51
+ data = data.slice(0, opts.length);
52
+ }
53
+ stream.end(data);
54
+ }, err => stream.error(err));
55
+ return stream;
56
+ }
57
+ watch(uri, _opts) {
58
+ const { resourceURI, server } = this._decodeURI(uri);
59
+ const cap = server.capabilities.get();
60
+ if (cap !== undefined && !(cap & McpCapability.ResourcesSubscribe)) {
61
+ return Disposable.None;
62
+ }
63
+ server.start();
64
+ const store = ( new DisposableStore());
65
+ let watchedOnHandler;
66
+ const watchListener = store.add(( new MutableDisposable()));
67
+ const callCts = store.add(( new MutableDisposable()));
68
+ store.add(autorun(reader => {
69
+ const connection = server.connection.read(reader);
70
+ if (!connection) {
71
+ return;
72
+ }
73
+ const handler = connection.handler.read(reader);
74
+ if (!handler || watchedOnHandler === handler) {
75
+ return;
76
+ }
77
+ callCts.value?.dispose(true);
78
+ callCts.value = ( new CancellationTokenSource());
79
+ watchedOnHandler = handler;
80
+ const token = callCts.value.token;
81
+ handler.subscribe({ uri: ( resourceURI.toString(true)) }, token).then(() => {
82
+ if (!token.isCancellationRequested) {
83
+ watchListener.value = handler.onDidUpdateResource(e => {
84
+ if (equalsUriPath(e.params.uri, resourceURI)) {
85
+ this._onDidChangeFile.fire([{ resource: uri, type: FileChangeType.UPDATED }]);
86
+ }
87
+ });
88
+ }
89
+ }, err => {
90
+ handler.logger.warn(`Failed to subscribe to resource changes for ${resourceURI}: ${err}`);
91
+ watchedOnHandler = undefined;
92
+ });
93
+ }));
94
+ return store;
95
+ }
96
+ async stat(resource) {
97
+ const { forSameURI, contents } = await this._readURI(resource);
98
+ if (!contents.length) {
99
+ throw createFileSystemProviderError(`File not found`, FileSystemProviderErrorCode.FileNotFound);
100
+ }
101
+ return {
102
+ ctime: 0,
103
+ mtime: 0,
104
+ size: sumBy(contents, c => contentToBuffer(c).byteLength),
105
+ type: forSameURI.length ? FileType.File : FileType.Directory,
106
+ };
107
+ }
108
+ async readdir(resource) {
109
+ const { forSameURI, contents, resourceURI } = await this._readURI(resource);
110
+ if (forSameURI.length > 0) {
111
+ throw createFileSystemProviderError(`File is not a directory`, FileSystemProviderErrorCode.FileNotADirectory);
112
+ }
113
+ const resourcePathParts = resourceURI.path.split('/');
114
+ const output = ( new Map());
115
+ for (const content of contents) {
116
+ const contentURI = ( URI.parse(content.uri));
117
+ const contentPathParts = contentURI.path.split('/');
118
+ if (contentPathParts.length <= resourcePathParts.length || !resourcePathParts.every((part, index) => equalsIgnoreCase(part, contentPathParts[index]))) {
119
+ continue;
120
+ }
121
+ else if (contentPathParts.length > resourcePathParts.length + 1) {
122
+ output.set(contentPathParts[resourcePathParts.length], FileType.Directory);
123
+ }
124
+ else {
125
+ const name = contentPathParts[contentPathParts.length - 1];
126
+ output.set(name, contentToBuffer(content).byteLength > 0 ? FileType.File : FileType.Directory);
127
+ }
128
+ }
129
+ return [...output];
130
+ }
131
+ mkdir(resource) {
132
+ throw createFileSystemProviderError('write is not supported', FileSystemProviderErrorCode.NoPermissions);
133
+ }
134
+ writeFile(resource, content, opts) {
135
+ throw createFileSystemProviderError('write is not supported', FileSystemProviderErrorCode.NoPermissions);
136
+ }
137
+ delete(resource, opts) {
138
+ throw createFileSystemProviderError('delete is not supported', FileSystemProviderErrorCode.NoPermissions);
139
+ }
140
+ rename(from, to, opts) {
141
+ throw createFileSystemProviderError('rename is not supported', FileSystemProviderErrorCode.NoPermissions);
142
+ }
143
+ async _readFile(resource, token) {
144
+ const { forSameURI, contents } = await this._readURI(resource);
145
+ if (!forSameURI.length) {
146
+ if (!contents.length) {
147
+ throw createFileSystemProviderError(`File not found`, FileSystemProviderErrorCode.FileNotFound);
148
+ }
149
+ else {
150
+ throw createFileSystemProviderError(`File is a directory`, FileSystemProviderErrorCode.FileIsADirectory);
151
+ }
152
+ }
153
+ return contentToBuffer(forSameURI[0]);
154
+ }
155
+ _decodeURI(uri) {
156
+ let definitionId;
157
+ let resourceURI;
158
+ try {
159
+ ({ definitionId, resourceURI } = McpResourceURI.toServer(uri));
160
+ }
161
+ catch (e) {
162
+ throw createFileSystemProviderError(String(e), FileSystemProviderErrorCode.FileNotFound);
163
+ }
164
+ if (resourceURI.path.endsWith('/')) {
165
+ resourceURI = resourceURI.with({ path: resourceURI.path.slice(0, -1) });
166
+ }
167
+ const server = this._mcpService.servers.get().find(s => s.definition.id === definitionId);
168
+ if (!server) {
169
+ throw createFileSystemProviderError(`MCP server ${definitionId} not found`, FileSystemProviderErrorCode.FileNotFound);
170
+ }
171
+ const cap = server.capabilities.get();
172
+ if (cap !== undefined && !(cap & McpCapability.Resources)) {
173
+ throw createFileSystemProviderError(`MCP server ${definitionId} does not support resources`, FileSystemProviderErrorCode.FileNotFound);
174
+ }
175
+ return { definitionId, resourceURI, server };
176
+ }
177
+ async _readURI(uri, token) {
178
+ const { resourceURI, server } = this._decodeURI(uri);
179
+ const res = await McpServer.callOn(server, r => r.readResource({ uri: ( resourceURI.toString(true)) }, token), token);
180
+ return {
181
+ contents: res.contents,
182
+ resourceURI,
183
+ forSameURI: res.contents.filter(c => equalsUriPath(c.uri, resourceURI)),
184
+ };
185
+ }
186
+ };
187
+ McpResourceFilesystem = ( __decorate([
188
+ ( __param(0, IInstantiationService)),
189
+ ( __param(1, IFileService))
190
+ ], McpResourceFilesystem));
191
+ function equalsUriPath(a, b) {
192
+ return equalsIgnoreCase(( URI.parse(a)).path, b.path);
193
+ }
194
+ function contentToBuffer(content) {
195
+ if ('text' in content) {
196
+ return VSBuffer.fromString(content.text).buffer;
197
+ }
198
+ else if ('blob' in content) {
199
+ return decodeBase64(content.blob).buffer;
200
+ }
201
+ else {
202
+ throw createFileSystemProviderError('Unknown content type', FileSystemProviderErrorCode.Unknown);
203
+ }
204
+ }
205
+
206
+ export { McpResourceFilesystem };
@@ -0,0 +1,26 @@
1
+ import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
2
+ import { IStorageService } from "@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service";
3
+ import { IMcpServer } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
4
+ import { MCP } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/modelContextProtocol";
5
+ interface ISamplingStoredData {
6
+ head: number;
7
+ bins: number[];
8
+ lastReqs: {
9
+ request: MCP.SamplingMessage[];
10
+ response: string;
11
+ at: number;
12
+ model: string;
13
+ }[];
14
+ }
15
+ export declare class McpSamplingLog extends Disposable {
16
+ private readonly _storageService;
17
+ private readonly _logs;
18
+ constructor(_storageService: IStorageService);
19
+ has(server: IMcpServer): boolean;
20
+ get(server: IMcpServer): Readonly<ISamplingStoredData | undefined>;
21
+ getAsText(server: IMcpServer): string;
22
+ private _formatRecentRequests;
23
+ add(server: IMcpServer, request: MCP.SamplingMessage[], response: string, model: string): Promise<void>;
24
+ private _getLogStorageForServer;
25
+ }
26
+ export {};
@@ -0,0 +1,110 @@
1
+
2
+ import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
+ import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
4
+ import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
5
+ import { observableMemento } from '@codingame/monaco-vscode-1cb11a73-359e-5a2f-9e95-6989cc9858ee-common/vscode/vs/platform/observable/common/observableMemento';
6
+ import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage';
7
+ import { IStorageService } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service';
8
+
9
+ var Constants;
10
+ (function (Constants) {
11
+ Constants[Constants["SamplingRetentionDays"] = 7] = "SamplingRetentionDays";
12
+ Constants[Constants["MsPerDay"] = 86400000] = "MsPerDay";
13
+ Constants[Constants["SamplingRetentionMs"] = 604800000] = "SamplingRetentionMs";
14
+ Constants[Constants["SamplingLastNMessage"] = 30] = "SamplingLastNMessage";
15
+ })(Constants || (Constants = {}));
16
+ const samplingMemento = observableMemento({
17
+ defaultValue: ( new Map()),
18
+ key: 'mcp.sampling.logs',
19
+ toStorage: v => JSON.stringify(Array.from(v.entries())),
20
+ fromStorage: v => ( new Map(JSON.parse(v))),
21
+ });
22
+ let McpSamplingLog = class McpSamplingLog extends Disposable {
23
+ constructor(_storageService) {
24
+ super();
25
+ this._storageService = _storageService;
26
+ this._logs = {};
27
+ }
28
+ has(server) {
29
+ const storage = this._getLogStorageForServer(server);
30
+ return ( storage.get().has(server.definition.id));
31
+ }
32
+ get(server) {
33
+ const storage = this._getLogStorageForServer(server);
34
+ return storage.get().get(server.definition.id);
35
+ }
36
+ getAsText(server) {
37
+ const storage = this._getLogStorageForServer(server);
38
+ const record = storage.get().get(server.definition.id);
39
+ if (!record) {
40
+ return '';
41
+ }
42
+ const parts = [];
43
+ const total = record.bins.reduce((sum, value) => sum + value, 0);
44
+ parts.push(( localize(7956, '{0} total requests in the last 7 days.', total)));
45
+ parts.push(this._formatRecentRequests(record));
46
+ return parts.join('\n');
47
+ }
48
+ _formatRecentRequests(data) {
49
+ if (!data.lastReqs.length) {
50
+ return '\nNo recent requests.';
51
+ }
52
+ const result = [];
53
+ for (let i = 0; i < data.lastReqs.length; i++) {
54
+ const { request, response, at, model } = data.lastReqs[i];
55
+ result.push(`\n[${i + 1}] ${( new Date(at)).toISOString()} ${model}`);
56
+ result.push(' Request:');
57
+ for (const msg of request) {
58
+ const role = msg.role.padEnd(9);
59
+ let content = '';
60
+ if ('text' in msg.content && msg.content.type === 'text') {
61
+ content = msg.content.text;
62
+ }
63
+ else if ('data' in msg.content) {
64
+ content = `[${msg.content.type} data: ${msg.content.mimeType}]`;
65
+ }
66
+ result.push(` ${role}: ${content}`);
67
+ }
68
+ result.push(' Response:');
69
+ result.push(` ${response}`);
70
+ }
71
+ return result.join('\n');
72
+ }
73
+ async add(server, request, response, model) {
74
+ const now = Date.now();
75
+ const utcOrdinal = Math.floor(now / Constants.MsPerDay);
76
+ const storage = this._getLogStorageForServer(server);
77
+ const next = ( new Map(storage.get()));
78
+ let record = next.get(server.definition.id);
79
+ if (!record) {
80
+ record = {
81
+ head: utcOrdinal,
82
+ bins: Array.from({ length: Constants.SamplingRetentionDays }, () => 0),
83
+ lastReqs: [],
84
+ };
85
+ }
86
+ else {
87
+ for (let i = 0; i < (utcOrdinal - record.head) && i < Constants.SamplingRetentionDays; i++) {
88
+ record.bins.pop();
89
+ record.bins.unshift(0);
90
+ }
91
+ record.head = utcOrdinal;
92
+ }
93
+ record.bins[0]++;
94
+ record.lastReqs.unshift({ request, response, at: now, model });
95
+ while (record.lastReqs.length > Constants.SamplingLastNMessage) {
96
+ record.lastReqs.pop();
97
+ }
98
+ next.set(server.definition.id, record);
99
+ storage.set(next, undefined);
100
+ }
101
+ _getLogStorageForServer(server) {
102
+ const scope = server.readDefinitions().get().collection?.scope ?? StorageScope.WORKSPACE;
103
+ return this._logs[scope] ??= this._register(samplingMemento(scope, StorageTarget.MACHINE, this._storageService));
104
+ }
105
+ };
106
+ McpSamplingLog = ( __decorate([
107
+ ( __param(0, IStorageService))
108
+ ], McpSamplingLog));
109
+
110
+ export { McpSamplingLog };
@@ -0,0 +1,38 @@
1
+ import { CancellationToken } from "@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation";
2
+ import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
3
+ import { ICommandService } from "@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service";
4
+ import { IConfigurationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service";
5
+ import { IDialogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service";
6
+ import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
7
+ import { INotificationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification.service";
8
+ import { ILanguageModelsService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/languageModels.service";
9
+ import { IMcpServerSamplingConfiguration } from "@codingame/monaco-vscode-aa9ead53-dfd3-59da-b9e7-f163d201de8d-common/vscode/vs/workbench/contrib/mcp/common/mcpConfiguration";
10
+ import { IMcpServer, ISamplingOptions, ISamplingResult } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
11
+ import { IMcpSamplingService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service";
12
+ export declare class McpSamplingService extends Disposable implements IMcpSamplingService {
13
+ private readonly _languageModelsService;
14
+ private readonly _configurationService;
15
+ private readonly _dialogService;
16
+ private readonly _notificationService;
17
+ private readonly _commandService;
18
+ readonly _serviceBrand: undefined;
19
+ private readonly _sessionSets;
20
+ private readonly _logs;
21
+ constructor(_languageModelsService: ILanguageModelsService, _configurationService: IConfigurationService, _dialogService: IDialogService, _notificationService: INotificationService, _commandService: ICommandService, instaService: IInstantiationService);
22
+ sample(opts: ISamplingOptions, token?: Readonly<CancellationToken>): Promise<ISamplingResult>;
23
+ hasLogs(server: IMcpServer): boolean;
24
+ getLogText(server: IMcpServer): string;
25
+ private _getMatchingModel;
26
+ private allowButtons;
27
+ private _showContextual;
28
+ private _notify;
29
+ private _getMatchingModelInner;
30
+ private _configKey;
31
+ getConfig(server: IMcpServer): IMcpServerSamplingConfiguration;
32
+ private _getConfig;
33
+ updateConfig(server: IMcpServer, mutate: (r: IMcpServerSamplingConfiguration) => unknown): Promise<{
34
+ allowedDuringChat?: boolean;
35
+ allowedOutsideChat?: boolean;
36
+ allowedModels?: string[];
37
+ }>;
38
+ }