mcp: initial hacking

This is some basic work to get MCP hooked up. It's enough to discover
and establish connections to MCP servers on the machine with very very
basic commands to manage them:

![](https://memes.peet.io/img/25-03-2220f93e-3d1f-41ab-867e-0b9ba616ec6f.mp4)

Refs #242864

The McpRegistry registers both collections of servers (from various
config files) and 'delegates', which is currently _only_ the node
extension host but is pretty generic and so could point at other
processes in the future. SSE could even be served from the renderer when
we aren't on a remote.

It wraps into IMcpServerConnection's, which do some basic connection
management and expose the McpServerRequestHandler which speaks JSON-RPC
to the MCP server. This is wrapped into the IMcpServer which is the
complete, stateful representation of the server. It does stuff like
caching discovered tools such that they can be viewed and controlled
even when the MCP server isn't running.

The IMcpService is the 'public' entry for other VS Code features. Its
API is very simple right now, exposing an observable of the available
servers, which should be easy for chat to consume.

Still need to get some good tests going, add proper and more discovery,
and excercise currently-untested API. SSE is also a stub right now.
This commit is contained in:
Connor Peet
2025-03-08 10:19:08 -08:00
parent fbfb939654
commit eb700003eb
21 changed files with 2909 additions and 2 deletions

View File

@@ -108,6 +108,7 @@ import { ProxyIdentifier } from '../../services/extensions/common/proxyIdentifie
import { ExcludeSettingOptions, TextSearchCompleteMessageType, TextSearchContext2, TextSearchMatch2 } from '../../services/search/common/searchExtTypes.js';
import type * as vscode from 'vscode';
import { ExtHostCodeMapper } from './extHostCodeMapper.js';
import { IExtHostMpcService } from './extHostMcp.js';
export interface IExtensionRegistries {
mine: ExtensionDescriptionRegistry;
@@ -218,6 +219,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostStatusBar = rpcProtocol.set(ExtHostContext.ExtHostStatusBar, new ExtHostStatusBar(rpcProtocol, extHostCommands.converter));
const extHostSpeech = rpcProtocol.set(ExtHostContext.ExtHostSpeech, new ExtHostSpeech(rpcProtocol));
const extHostEmbeddings = rpcProtocol.set(ExtHostContext.ExtHostEmbeddings, new ExtHostEmbeddings(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostMcp, accessor.get(IExtHostMpcService));
// Check that no named customers are missing
const expected = Object.values<ProxyIdentifier<any>>(ExtHostContext);