1
>
/*---------------------------------------------------------------------------------------------
extHostMcp.ts
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 * as vscode from 'vscode';
7
>
import { DeferredPromise, raceCancellationError, Sequencer, timeout } from '../../../base/common/async.js';
8
>
import { CancellationToken, CancellationTokenSource } from '../../../base/common/cancellation.js';
9
>
import { CancellationError } from '../../../base/common/errors.js';
10
>
import { Emitter, Event } from '../../../base/common/event.js';
11
>
import { Disposable, DisposableMap, DisposableStore, IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
12
>
import { AUTH_SCOPE_SEPARATOR, fetchAuthorizationServerMetadata, fetchResourceMetadata, getDefaultMetadataForUrl, IAuthorizationProtectedResourceMetadata, IAuthorizationServerMetadata, parseWWWAuthenticateHeader, scopesMatch } from '../../../base/common/oauth.js';
13
>
import { SSEParser } from '../../../base/common/sseParser.js';
14
>
import { URI, UriComponents } from '../../../base/common/uri.js';
15
>
import { vArray, vNumber, vObj, vObjAny, vOptionalProp, vString } from '../../../base/common/validation.js';
16
>
import { ConfigurationTarget } from '../../../platform/configuration/common/configuration.js';
17
>
import { ExtensionIdentifier, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
18
>
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
19
>
import { canLog, ILogService, LogLevel } from '../../../platform/log/common/log.js';
20
>
import product from '../../../platform/product/common/product.js';
21
>
import { StorageScope } from '../../../platform/storage/common/storage.js';
22
>
import { extensionPrefixedIdentifier, McpCollectionDefinition, McpConnectionState, McpServerDefinition, McpServerLaunch, McpServerStaticMetadata, McpServerStaticToolAvailability, McpServerTransportHTTP, McpServerTransportType, UserInteractionRequiredError } from '../../contrib/mcp/common/mcpTypes.js';
23
>
import { MCP } from '../../contrib/mcp/common/modelContextProtocol.js';
24
>
import { checkProposedApiEnabled, isProposedApiEnabled } from '../../services/extensions/common/extensions.js';
25
>
import { ExtHostMcpShape, IMcpAuthenticationDetails, IAuthMetadataSource, IStartMcpOptions, MainContext, MainThreadMcpShape, IAuthResourceMetadataSource, IAuthServerMetadataSource } from './extHost.protocol.js';
26
>
import { IExtHostInitDataService } from './extHostInitDataService.js';
27
>
import { IExtHostRpcService } from './extHostRpcService.js';
28
>
import * as Convert from './extHostTypeConverters.js';
29
>
import { McpHttpServerDefinition, McpStdioServerDefinition, McpToolAvailability } from './extHostTypes.js';
30
>
import { IExtHostVariableResolverProvider } from './extHostVariableResolverService.js';
31
>
import { IExtHostWorkspace } from './extHostWorkspace.js';
32
>
33
>
export const IExtHostMpcService = createDecorator<IExtHostMpcService>('IExtHostMpcService');
34
>
35
>
export interface IExtHostMpcService extends ExtHostMcpShape {
36
>
registerMcpConfigurationProvider(extension: IExtensionDescription, id: string, provider: vscode.McpServerDefinitionProvider): IDisposable;
37
>
38
>
/** Event that fires when the set of MCP server definitions changes. */
39
>
readonly onDidChangeMcpServerDefinitions: Event<void>;
40
>
41
>
/** Returns all MCP server definitions known to the editor. */
42
>
readonly mcpServerDefinitions: readonly vscode.McpServerDefinition[];
43
>
44
>
/** Starts an MCP gateway that exposes MCP servers via HTTP endpoints. */
45
>
startMcpGateway(chatSessionResource?: URI): Promise<vscode.McpGateway | undefined>;
46
>
}
47
>
48
>
const serverDataValidation = vObj({
49
>
label: vString(),
50
>
version: vOptionalProp(vString()),
51
>
metadata: vOptionalProp(vObj({
52
>
capabilities: vOptionalProp(vObjAny()),
53
>
serverInfo: vOptionalProp(vObjAny()),
54
>
tools: vOptionalProp(vArray(vObj({
55
>
availability: vNumber(),
56
>
definition: vObjAny(),
57
>
}))),
58
>
})),
59
>
authentication: vOptionalProp(vObj({
60
>
providerId: vString(),
61
>
scopes: vArray(vString()),
62
>
}))
63
>
});
64
>
65
>
// Can be validated with:
66
>
// declare const _serverDataValidationTest: vscode.McpStdioServerDefinition | vscode.McpHttpServerDefinition;
67
>
// const _serverDataValidationProd: ValidatorType<typeof serverDataValidation> = _serverDataValidationTest;
68
>
69
>
export class ExtHostMcpService extends Disposable implements IExtHostMpcService {
70
>
protected _proxy: MainThreadMcpShape;
71
>
private readonly _initialProviderPromises = new Set<Promise<void>>();
72
>
protected readonly _sseEventSources = this._register(new DisposableMap<number, McpHTTPHandle>());
73
>
private readonly _unresolvedMcpServers = new Map</* collectionId */ string, {
74
>
provider: vscode.McpServerDefinitionProvider;
75
>
servers: vscode.McpServerDefinition[];
76
>
}>();
77
>
78
>
// MCP server definitions synced from main thread
79
>
private readonly _onDidChangeMcpServerDefinitions = this._register(new Emitter<void>());
80
>
readonly onDidChangeMcpServerDefinitions: Event<void> = this._onDidChangeMcpServerDefinitions.event;
81
>
private _mcpServerDefinitions: readonly vscode.McpServerDefinition[] = [];
82
>
83
>
// Active gateways with their server emitters for dynamic updates
84
>
private readonly _activeGateways = new Map<string, {
85
>
servers: vscode.McpGatewayServer[];
86
>
onDidChangeServers: Emitter<readonly vscode.McpGatewayServer[]>;
87
>
}>();
88
>
89
>
constructor(
90
@IExtHostRpcService extHostRpc: IExtHostRpcService,
91
@ILogService protected readonly _logService: ILogService,