update state

This commit is contained in:
Andrew Pareles
2025-05-21 01:38:15 -07:00
parent 4d8363026e
commit 13654389c6
5 changed files with 165 additions and 235 deletions
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------*/
import React, { useState, useEffect, useCallback } from 'react'
import { RefreshableProviderName, SettingsOfProvider } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js'
import { MCPServerState, RefreshableProviderName, SettingsOfProvider } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js'
import { IDisposable } from '../../../../../../../base/common/lifecycle.js'
import { VoidSettingsState } from '../../../../../../../workbench/contrib/void/common/voidSettingsService.js'
import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js'
@@ -79,6 +79,8 @@ const ctrlKZoneStreamingStateListeners: Set<(diffareaid: number, s: boolean) =>
const commandBarURIStateListeners: Set<(uri: URI) => void> = new Set();
const activeURIListeners: Set<(uri: URI | null) => void> = new Set();
const mcpListeners: Set<() => void> = new Set()
// must call this before you can use any of the hooks below
// this should only be called ONCE! this is the only place you don't need to dispose onDidChange. If you use state.onDidChange anywhere else, make sure to dispose it!
@@ -96,9 +98,10 @@ export const _registerServices = (accessor: ServicesAccessor) => {
editCodeService: accessor.get(IEditCodeService),
voidCommandBarService: accessor.get(IVoidCommandBarService),
modelService: accessor.get(IModelService),
mcpService: accessor.get(IMCPService),
}
const { settingsStateService, chatThreadsStateService, refreshModelService, themeService, editCodeService, voidCommandBarService, modelService } = stateServices
const { settingsStateService, chatThreadsStateService, refreshModelService, themeService, editCodeService, voidCommandBarService, modelService, mcpService } = stateServices
@@ -165,6 +168,11 @@ export const _registerServices = (accessor: ServicesAccessor) => {
})
)
disposables.push(
mcpService.onDidChangeState(() => {
mcpListeners.forEach(l => l())
})
)
return disposables
@@ -378,3 +386,16 @@ export const useActiveURI = () => {
export const useMCPServiceState = () => {
const accessor = useAccessor()
const mcpService = accessor.get('IMCPService')
const [s, ss] = useState(mcpService.state)
useEffect(() => {
const listener = () => { ss(mcpService.state) }
mcpListeners.add(listener);
return () => { mcpListeners.delete(listener) };
}, []);
return s
}
@@ -1,7 +1,7 @@
import { VoidSwitch } from '../util/inputs.js';
import { MCPConfigFileParseErrorResponse, MCPEventType, MCPEventResponse, MCPServerObject, MCPServerOfName } from '../../../../common/mcpServiceTypes.js';
import { MCPConfigFileParseErrorResponse, MCPServerEventType, MCPServerEventResponse, MCPServerObject, MCPServerOfName } from '../../../../common/mcpServiceTypes.js';
import { useEffect, useState } from 'react';
import { useAccessor } from '../util/services.js';
import { useAccessor, useMCPServiceState } from '../util/services.js';
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
// Command display component
@@ -96,80 +96,49 @@ const MCPServer = ({ name, server }: { name: string, server: MCPServerObject })
// Main component that renders the list of servers
const MCPServersList = () => {
const accessor = useAccessor();
const mcpService = accessor.get('IMCPService');
const [mcpServers, setMCPServers] = useState<MCPServerOfName>({});
const [mcpConfigError, setMCPConfigError] = useState<string | null>(null);
const mcpServiceState = useMCPServiceState()
// Get all servers from MCPConfigService
useEffect(() => {
console.log('RUNNING MCPServersList EFFECT');
// Initial fetch
const servers = mcpService.getMCPServerOfName();
if (servers) {
// Do something with the servers
console.log('MCP Servers:', servers);
setMCPServers(servers);
}
// const handleListeners = (e: MCPServerEventResponse | MCPConfigFileParseErrorResponse) => {
// if (e.response.type === 'config-file-error') {
// // Handle the config error event
// const { error } = e.response;
// setMCPConfigError(error);
// return;
// }
// if (e.response.type === 'add' || e.response.type === 'update' || e.response.type === 'loading') {
// // Handle the add event
// const { name, newServer } = e.response;
// setMCPServers(prevServers => ({
// ...prevServers,
// [name]: newServer
// }));
// return;
// }
// if (e.response.type === 'delete') {
// // Handle the delete event
// const { name, prevServer } = e.response;
// setMCPServers(prevServers => {
// const newServers = { ...prevServers };
// delete newServers[name];
// return newServers;
// });
// return;
// }
// throw new Error('Event not handled');
// }
// Set up listeners for server events
const disposables: IDisposable[] = []
disposables.push(mcpService.onDidAddServer(handleListeners));
disposables.push(mcpService.onDidDeleteServer(handleListeners));
disposables.push(mcpService.onDidUpdateServer(handleListeners));
// disposables.push(mcpService.onLoadingServers(handleListeners));
disposables.push(mcpService.onConfigParsingError(handleListeners));
// Clean up subscription when component unmounts
return () => {
console.log('Cleaning up subscriptions');
disposables.forEach(disposable => disposable.dispose());
};
}, [mcpService]);
const handleListeners = (e: MCPEventResponse | MCPConfigFileParseErrorResponse) => {
if (e.response.type === 'config-file-error') {
// Handle the config error event
const { error } = e.response;
setMCPConfigError(error);
return;
}
if (e.response.type === 'add' || e.response.type === 'update' || e.response.type === 'loading') {
// Handle the add event
const { name, newServer } = e.response;
setMCPServers(prevServers => ({
...prevServers,
[name]: newServer
}));
return;
}
if (e.response.type === 'delete') {
// Handle the delete event
const { name, prevServer } = e.response;
setMCPServers(prevServers => {
const newServers = { ...prevServers };
delete newServers[name];
return newServers;
});
return;
}
throw new Error('Event not handled');
}
return (
<div className="text-white rounded-md py-4">
<div>
{!mcpConfigError && Object.entries(mcpServers).map(([name, server]) => (
{!mcpServiceState.error && Object.entries(mcpServiceState.mcpServerOfName).map(([name, server]) => (
<div className="py-2" key={name}>
<MCPServer name={name} server={server} />
</div>
))}
{mcpConfigError && (
{mcpServiceState.error && (
<div className="text-red-500 text-sm font-medium">
{mcpConfigError}
{mcpServiceState.error}
</div>
)}
</div>
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------*/
import { URI } from '../../../../base/common/uri.js';
import { Disposable, IDisposable } from '../../../../base/common/lifecycle.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { IFileService } from '../../../../platform/files/common/files.js';
@@ -15,58 +15,55 @@ import { IProductService } from '../../../../platform/product/common/productServ
import { VSBuffer } from '../../../../base/common/buffer.js';
import { IChannel } from '../../../../base/parts/ipc/common/ipc.js';
import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js';
import { MCPServerOfName, MCPConfigFileType, MCPConfigFileParseErrorResponse, MCPAddResponse, MCPUpdateResponse, MCPDeleteResponse, MCPEventResponse } from './mcpServiceTypes.js';
import { MCPServerOfName, MCPConfigFileType, MCPAddServerResponse, MCPUpdateServerResponse, MCPDeleteServerResponse, MCPServerEventResponse, MCPServerObject } from './mcpServiceTypes.js';
import { Event, Emitter } from '../../../../base/common/event.js';
import { InternalToolInfo } from './prompt/prompts.js';
import { IVoidSettingsService } from './voidSettingsService.js';
import { MCPServerStateOfName } from './voidSettingsTypes.js';
type MCPState = {
mcpServerOfName: MCPServerOfName,
error: string | undefined,
}
export interface IMCPService {
readonly _serviceBrand: undefined;
revealMCPConfigFile(): Promise<void>;
getMCPServerOfName(): MCPServerOfName;
getCurrentTools(): InternalToolInfo[];
toggleServer(serverName: string, isOn: boolean): Promise<void>;
onDidAddServer: Event<MCPAddResponse>;
onDidUpdateServer: Event<MCPUpdateResponse>;
onDidDeleteServer: Event<MCPDeleteResponse>;
readonly state: MCPState;
onDidChangeState: Event<void>;
// onLoadingServers: Event<MCPServerEventLoadingParam>;
onConfigParsingError: Event<MCPConfigFileParseErrorResponse>;
getCurrentMCPTools(): InternalToolInfo[];
}
export const IMCPService = createDecorator<IMCPService>('mcpConfigService');
const MCP_CONFIG_FILE_NAME = 'mcp.json';
const MCP_CONFIG_SAMPLE = { mcpServers: {} }
const MCP_CONFIG_SAMPLE_STRING = JSON.stringify(MCP_CONFIG_SAMPLE, null, 2);
class MCPService extends Disposable implements IMCPService {
_serviceBrand: undefined;
private readonly MCP_CONFIG_FILE_NAME = 'mcp.json';
private readonly MCP_CONFIG_SAMPLE = {
mcpServers: {},
}
private readonly MCP_CONFIG_SAMPLE_STRING = JSON.stringify(this.MCP_CONFIG_SAMPLE, null, 2);
private mcpFileWatcher: IDisposable | null = null;
private readonly channel: IChannel // MCPChannel
// list of MCP servers pulled from mcpChannel
private readonly mcpServers: MCPServerOfName = {}
state: MCPState = {
mcpServerOfName: {},
error: undefined
}
// Emitters for server events
private readonly _onDidAddServer = new Emitter<MCPAddResponse>();
private readonly _onDidUpdateServer = new Emitter<MCPUpdateResponse>();
private readonly _onDidDeleteServer = new Emitter<MCPDeleteResponse>();
public readonly onDidAddServer = this._onDidAddServer.event;
public readonly onDidUpdateServer = this._onDidUpdateServer.event;
public readonly onDidDeleteServer = this._onDidDeleteServer.event;
private readonly _onDidChangeState = new Emitter<void>();
public readonly onDidChangeState = this._onDidChangeState.event;
// private readonly _onLoadingServers = new Emitter<MCPServerEventLoadingParam>();
// public readonly onLoadingServers = this._onLoadingServers.event;
private readonly _onConfigParsingError = new Emitter<MCPConfigFileParseErrorResponse>();
public readonly onConfigParsingError = this._onConfigParsingError.event;
// private readonly _onLoadingServersChange = new Emitter<MCPServerEventLoadingParam>();
// public readonly onLoadingServersChange = this._onLoadingServersChange.event;
constructor(
@IFileService private readonly fileService: IFileService,
@@ -80,108 +77,79 @@ class MCPService extends Disposable implements IMCPService {
// Register the service with the instantiation service
this.channel = this.mainProcessService.getChannel('void-channel-mcp')
// Register listeners for the channel
this._register((this.channel.listen('onAdd_server') satisfies Event<MCPAddResponse>)(e => this._onServerEvent(e)));
this._register((this.channel.listen('onUpdate_server') satisfies Event<MCPUpdateResponse>)(e => this._onServerEvent(e)));
this._register((this.channel.listen('onDelete_server') satisfies Event<MCPDeleteResponse>)(e => this._onServerEvent(e)));
this._register((this.channel.listen('onAdd_server') satisfies Event<MCPAddServerResponse>)(e => this._onGetServerEvent(e)));
this._register((this.channel.listen('onUpdate_server') satisfies Event<MCPUpdateServerResponse>)(e => this._onGetServerEvent(e)));
this._register((this.channel.listen('onDelete_server') satisfies Event<MCPDeleteServerResponse>)(e => this._onGetServerEvent(e)));
// this._register((this.channel.listen('onLoading_server') satisfies Event<MCPServerEventLoadingParam>)(e => this._onServerEvent(e)));
// Initialize the service
this._initialize();
}
// This method is called when the service is disposed
override async dispose(): Promise<void> {
// Custom cleanup logic goes here
console.log('MCPService is being disposed');
// Call _removeMCPConfigFileWatch to clean up file watchers
this._removeMCPConfigFileWatch().catch(err => {
console.error('Error removing MCP config file watch:', err);
});
// Close all servers in electron main process
await this.channel.call('closeAllServers')
// Always call the parent class dispose method to ensure proper cleanup
super.dispose();
}
private async _initialize() {
try {
// Get the MCP config file path
const mcpConfigUri = await this._getMCPConfigFilePath();
await this.voidSettingsService.waitForInitState;
// create file if it doesn't exist
// Create .mcpConfig if it doesn't exist
const mcpConfigUri = await this._getMCPConfigFilePath();
const fileExists = await this._configFileExists(mcpConfigUri);
if (!fileExists) {
await this._createMCPConfigFile(mcpConfigUri);
console.log('MCP Config file created:', mcpConfigUri.toString());
}
// Wait for VoidSettingsService to initialize before proceeding
await this.voidSettingsService.waitForInitState;
// read MCP config file
const mcpConfig = await this._parseMCPConfigFile();
if (!mcpConfig) throw new Error(`MCP config file not found`);
if (!mcpConfig.mcpServers) throw new Error(`MCP config file did not have an 'mcpServers' field`);
// update state based on config file
const updatedServerStates = await this._handleServerStateChange(mcpConfig);
// Setup the server list
this.channel.call('setupServers', { mcpConfig, serverStates: updatedServerStates })
await this._updateStateWithCurrentConfigFile();
// Add a watcher to the MCP config file
await this._setMCPConfigFileWatch();
await this._addMCPConfigFileWatcher();
} catch (error) {
console.error('Error initializing MCPService:', error);
}
}
private async _onServerEvent(e: MCPEventResponse) {
const r = e.response
if (r.type === 'add') {
this.mcpServers[r.name] = r.newServer;
this._onDidAddServer.fire(e as MCPAddResponse);
}
if (r.type === 'update') {
this.mcpServers[r.name] = r.newServer;
this._onDidUpdateServer.fire(e as MCPUpdateResponse);
}
if (r.type === 'delete') {
delete this.mcpServers[r.name];
this._onDidDeleteServer.fire(e as MCPDeleteResponse);
}
// if (e.response.event === 'loading') {
// // Update the mcpServers list
// this.mcpServers[e.response.name] = e.response.newServer;
// // Fire the event to notify browser
// this._onLoadingServers.fire(e);
// }
private async _onGetServerEvent(e: MCPServerEventResponse) {
this._setMCPServer(e.response.name, e.response.newServer)
}
private readonly _setMCPServer = async (serverName: string, newServer: MCPServerObject | undefined) => {
this.state = {
...this.state,
mcpServerOfName: {
...this.state.mcpServerOfName,
...newServer === undefined ? {} : { [serverName]: newServer, }
}
}
this._onDidChangeState.fire();
}
private readonly _setHasError = async (hasError: string | undefined) => {
this.state = {
...this.state,
error: hasError ? `MCP config file not found` : undefined,
}
this._onDidChangeState.fire();
}
// Create the file/directory if it doesn't exist
private async _createMCPConfigFile(mcpConfigUri: URI): Promise<void> {
await this.fileService.createFile(mcpConfigUri.with({ path: mcpConfigUri.path }));
const buffer = VSBuffer.fromString(this.MCP_CONFIG_SAMPLE_STRING);
const buffer = VSBuffer.fromString(MCP_CONFIG_SAMPLE_STRING);
await this.fileService.writeFile(mcpConfigUri, buffer);
}
// Remove any previous config parsing error
// This isn't super intuitive, but it works
private async _parseMCPConfigFile(): Promise<MCPConfigFileType | null> {
// clear error
this._onConfigParsingError.fire({
response: {
type: 'config-file-error',
error: null
}
});
// TODO!!!!!!! double check this
// this._onConfigParsingError.fire({
// response: {
// type: 'config-file-error',
// error: null
// }
// });
// Process config file
const mcpConfigUri = await this._getMCPConfigFilePath();
@@ -196,53 +164,28 @@ class MCPService extends Disposable implements IMCPService {
return configJson as MCPConfigFileType;
} catch (error) {
const fullError = `Error parsing MCP config file: ${error}`;
console.error(fullError);
this._onConfigParsingError.fire({
response: {
type: 'config-file-error',
error: fullError
}
});
this._setHasError(fullError)
return null;
}
}
private async _setMCPConfigFileWatch(): Promise<void> {
private async _addMCPConfigFileWatcher(): Promise<void> {
const mcpConfigUri = await this._getMCPConfigFilePath();
this._register(
this.fileService.watch(mcpConfigUri)
)
// Watch the file for changes
this.mcpFileWatcher = this.fileService.watch(mcpConfigUri);
// Listen for changes
this._register(this.fileService.onDidFilesChange(async e => {
// Handle file changes
if (e.contains(mcpConfigUri)) {
const mcpConfig = await this._parseMCPConfigFile();
if (mcpConfig && mcpConfig.mcpServers) {
const updatedServerStates = await this._handleServerStateChange(mcpConfig);
// Set up the server list
this.channel.call('setupServers', { mcpConfig, serverStates: updatedServerStates })
}
}
if (!e.contains(mcpConfigUri)) return
await this._updateStateWithCurrentConfigFile();
}));
}
private async _removeMCPConfigFileWatch(): Promise<void> {
if (this.mcpFileWatcher) {
this.mcpFileWatcher.dispose();
this.mcpFileWatcher = null;
}
}
// Client-side functions
public async revealMCPConfigFile(): Promise<void> {
try {
// Get the MCP config file path
const mcpConfigUri = await this._getMCPConfigFilePath();
// Open the MCP config file in the editor
await this.editorService.openEditor({
resource: mcpConfigUri,
options: {
@@ -250,19 +193,13 @@ class MCPService extends Disposable implements IMCPService {
revealIfOpened: true,
}
});
} catch (error) {
console.error('Error opening MCP config file:', error);
}
}
public getMCPServerOfName(): MCPServerOfName {
// Call the getMCPServers method in the main process
return this.mcpServers;
}
public getCurrentTools(): InternalToolInfo[] {
const allTools = Object.values(this.mcpServers).flatMap(server => {
public getCurrentMCPTools(): InternalToolInfo[] {
const allTools = Object.values(this.state.mcpServerOfName).flatMap(server => {
return server.tools.map(tool => {
// Convert JsonSchema to the expected format
const convertedParams: { [paramName: string]: { description: string } } = {};
@@ -295,31 +232,32 @@ class MCPService extends Disposable implements IMCPService {
// utility functions
private async _getMCPConfigFilePath(): Promise<URI> {
// Get the appropriate directory based on dev mode
const appName = this.productService.dataFolderName
const userHome = await this.pathService.userHome();
const mcpConfigPath = join(userHome.path, appName, this.MCP_CONFIG_FILE_NAME);
const mcpConfigPath = join(userHome.path, appName, MCP_CONFIG_FILE_NAME);
return URI.file(mcpConfigPath);
}
private async _configFileExists(mcpConfigUri: URI): Promise<boolean> {
try {
// Try to get file stats - if it succeeds, the file exists
await this.fileService.stat(mcpConfigUri);
return true;
} catch (error) {
// File doesn't exist or can't be accessed
return false;
}
}
// Handle server state changes
private async _handleServerStateChange(mcpConfig: MCPConfigFileType): Promise<MCPServerStateOfName> {
// Get the server states from Void Settings Service
const savedServerStates = this.voidSettingsService.state.mcpServerStateOfName;
private async _updateStateWithCurrentConfigFile(): Promise<void> {
// Parse the MCP config file for servers
const availableServers = Object.keys(mcpConfig.mcpServers);
this._setHasError(undefined)
const mcpConfigFile = await this._parseMCPConfigFile();
if (!mcpConfigFile) { console.log(`Not setting state: MCP config file not found`); return }
if (!mcpConfigFile?.mcpServers) { console.log(`Not setting state: MCP config file did not have an 'mcpServers' field`); return }
const savedServerStates = this.voidSettingsService.state.mcpServerStateOfName;
const availableServers = Object.keys(mcpConfigFile.mcpServers);
// Handle added servers
const addedServers = availableServers.filter(serverName => !savedServerStates[serverName]);
@@ -341,7 +279,7 @@ class MCPService extends Disposable implements IMCPService {
return acc;
}, {} as MCPServerStateOfName);
return updatedServers;
this.channel.call('refreshMCPServers', { mcpConfig: mcpConfigFile, serverStates: updatedServers })
}
}
@@ -165,7 +165,7 @@ export type EventMCPServerSetupOnError = Parameters<MCPServerSetupParams['onErro
export type MCPServerModel = MCPServerSuccessModel | MCPServerErrorModel;
export type MCPEventType = {
export type MCPServerEventType = {
type: 'add';
name: string;
prevServer?: undefined;
@@ -188,13 +188,13 @@ export type MCPEventType = {
}
// Response types
export type MCPAddResponse = { response: MCPEventType & { type: 'add' } }
export type MCPUpdateResponse = { response: MCPEventType & { type: 'update' } }
export type MCPDeleteResponse = { response: MCPEventType & { type: 'delete' } }
// export type MCPLoadingResponse = { response: MCPEventType & { type: 'loading' } }
export type MCPAddServerResponse = { response: MCPServerEventType & { type: 'add' } }
export type MCPUpdateServerResponse = { response: MCPServerEventType & { type: 'update' } }
export type MCPDeleteServerResponse = { response: MCPServerEventType & { type: 'delete' } }
// export type MCPLoadingChangeResponse = { response: MCPEventType & { type: 'loading' } }
export type MCPEventResponse = { response: MCPEventType }
export type MCPServerEventResponse = { response: MCPServerEventType }
export interface MCPConfigFileParseErrorResponse {
response: {
@@ -13,7 +13,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { MCPConfigFileType, MCPConfigFileServerType, MCPServerErrorModel, MCPServerModel, MCPAddResponse, MCPUpdateResponse, MCPDeleteResponse } from '../common/mcpServiceTypes.js';
import { MCPConfigFileType, MCPConfigFileServerType, MCPServerErrorModel, MCPServerModel, MCPAddServerResponse, MCPUpdateServerResponse, MCPDeleteServerResponse } from '../common/mcpServiceTypes.js';
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import { equals } from '../../../../base/common/objects.js';
import { MCPServerStateOfName } from '../common/voidSettingsTypes.js';
@@ -52,10 +52,12 @@ export class MCPChannel implements IServerChannel {
// mcp emitters
private readonly mcpEmitters = {
serverEvent: {
onAdd: new Emitter<MCPAddResponse>(),
onUpdate: new Emitter<MCPUpdateResponse>(),
onDelete: new Emitter<MCPDeleteResponse>(),
// onChangeLoading: new Emitter<MCPLoadingResponse>(),
onAdd: new Emitter<MCPAddServerResponse>(),
onUpdate: new Emitter<MCPUpdateServerResponse>(),
onDelete: new Emitter<MCPDeleteServerResponse>(),
// onResult: new Emitter<>(),
// onError: new Emitter<>(),
// onChangeLoading: new Emitter<MCPLoadingResponse>(), // really onStart
}
// toolCall: {
// success: new Emitter<void>(),
@@ -63,9 +65,9 @@ export class MCPChannel implements IServerChannel {
// },
} satisfies {
serverEvent: {
onAdd: Emitter<MCPAddResponse>,
onUpdate: Emitter<MCPUpdateResponse>,
onDelete: Emitter<MCPDeleteResponse>,
onAdd: Emitter<MCPAddServerResponse>,
onUpdate: Emitter<MCPUpdateServerResponse>,
onDelete: Emitter<MCPDeleteServerResponse>,
// onChangeLoading: Emitter<MCPLoadingResponse>,
}
}
@@ -90,11 +92,11 @@ export class MCPChannel implements IServerChannel {
// browser uses this to call (see this.channel.call() in mcpConfigService.ts for all usages)
async call(_: unknown, command: string, params: any): Promise<any> {
try {
if (command === 'setupServers') {
await this._setupServers(params)
if (command === 'refreshMCPServers') {
await this._refreshMCPServers(params)
}
else if (command === 'closeAllServers') {
await this._closeAllServers()
else if (command === 'closeAllMCPServers') {
await this._closeAllMCPServers()
}
else if (command === 'toggleServer') {
await this._toggleServer(params.serverName, params.isOn)
@@ -114,7 +116,7 @@ export class MCPChannel implements IServerChannel {
// call functions
private async _setupServers(params: { mcpConfig: MCPConfigFileType, serverStates: MCPServerStateOfName }) {
private async _refreshMCPServers(params: { mcpConfig: MCPConfigFileType, serverStates: MCPServerStateOfName }) {
const { mcpConfig, serverStates } = params
@@ -313,7 +315,7 @@ export class MCPChannel implements IServerChannel {
}
}
private async _closeAllServers() {
private async _closeAllMCPServers() {
for (const serverName in this.clients) {
await this._closeServer(serverName)
this._removeServer(serverName)