From 5f7f07ee6fa8299e0b42172ec7cbd3738a521580 Mon Sep 17 00:00:00 2001 From: dimitrievgs Date: Sun, 14 Jun 2026 23:15:46 +0300 Subject: [PATCH] Add enable-toggles for mcp servers and particular tools --- main.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/main.ts b/main.ts index f908a2a..601bfde 100644 --- a/main.ts +++ b/main.ts @@ -18,6 +18,7 @@ export interface MCPToolState { name: string; originalDescription: string; customDescription: string; + isEnabled?: boolean; } export interface MCPServerConfig { @@ -28,6 +29,7 @@ export interface MCPServerConfig { envString: string; serverInstruction?: string; fetchedTools?: MCPToolState[]; + isEnabled?: boolean; } // ----------------------------------------------- Settings --------------------------------------------------------------- @@ -667,12 +669,25 @@ class SampleSettingTab extends PluginSettingTab { if (!this.plugin.settings.mcpServers) this.plugin.settings.mcpServers = []; this.plugin.settings.mcpServers.forEach((server, index) => { + if (server.isEnabled === undefined) server.isEnabled = true; + const serverDiv = container.createDiv({ - attr: { style: 'border: 1px solid var(--interactive-accent); padding: 10px; margin-bottom: 15px; border-radius: 8px; background-color: var(--background-secondary-alt);' } + attr: { style: `border: 1px solid var(--interactive-accent); padding: 10px; margin-bottom: 15px; border-radius: 8px; background-color: var(--background-secondary-alt); transition: opacity 0.3s; opacity: ${server.isEnabled ? '1' : '0.5'}` } }); new Setting(serverDiv) .setName(`Имя сервера`) + .addToggle(tg => tg + .setTooltip(server.isEnabled ? 'Выключить сервер' : 'Включить сервер') + .setValue(server.isEnabled!) + .onChange(async v => { + server.isEnabled = v; + serverDiv.style.opacity = v ? '1' : '0.5'; + tg.setTooltip(v ? 'Выключить сервер' : 'Включить сервер'); + await this.plugin.saveSettings(); + await this.plugin.syncSettings(); // Мгновенно синхроним с бэкендом + }) + ) .addText(t => t.setValue(server.name).onChange(async v => { server.name = v.replace(/[^a-zA-Z0-9_\-]/g, ''); await this.plugin.saveSettings(); @@ -732,7 +747,7 @@ class SampleSettingTab extends PluginSettingTab { }); new Setting(container).addButton(b => b.setButtonText('➕ Добавить MCP сервер').setCta().onClick(async () => { - this.plugin.settings.mcpServers.push({ id: uuidv4(), name: 'duckduckgo', command: 'docker', args: 'run -i --rm ddg-mcp-server', envString: '' }); + this.plugin.settings.mcpServers.push({ id: uuidv4(), name: 'duckduckgo', command: 'docker', args: 'run -i --rm ddg-mcp-server', envString: '', isEnabled: true }); await this.plugin.saveSettings(); this.display(); })); @@ -767,7 +782,7 @@ class SampleSettingTab extends PluginSettingTab { const existing = existingMap.get(rt.name)!; return { ...existing, originalDescription: rt.description }; // обновляем оригинальное описание на всякий случай } - return { name: rt.name, originalDescription: rt.description, customDescription: '' }; + return { name: rt.name, originalDescription: rt.description, customDescription: '', isEnabled: true }; }); await this.plugin.saveSettings(); @@ -785,13 +800,39 @@ class SampleSettingTab extends PluginSettingTab { // Отрисовка списка тулов if (server.fetchedTools && server.fetchedTools.length > 0) { server.fetchedTools.forEach((tool, tIndex) => { - const toolDiv = toolsContainer.createDiv({ attr: { style: 'margin-bottom: 10px; padding: 10px; background: var(--background-primary); border-radius: 6px;' } }); - toolDiv.createEl('div', { text: `🛠 ${tool.name}`, attr: { style: 'font-weight: bold; margin-bottom: 5px;' } }); + if (tool.isEnabled === undefined) tool.isEnabled = true; + + const toolDiv = toolsContainer.createDiv({ + attr: { style: `margin-bottom: 10px; padding: 10px; background: var(--background-primary); border-radius: 6px; transition: opacity 0.3s; opacity: ${tool.isEnabled ? '1' : '0.5'}` } + }); + + // Заголовок тула с переключателем + const headerDiv = toolDiv.createDiv({ attr: { style: 'display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 5px;' } }); + headerDiv.createEl('div', { text: `🛠 ${tool.name}`, attr: { style: 'font-weight: bold; margin-top: 5px;' } }); + + const toggleSetting = new Setting(headerDiv) + .addToggle(tg => tg + .setTooltip(tool.isEnabled ? 'Выключить инструмент' : 'Включить инструмент') + .setValue(tool.isEnabled!) + .onChange(async v => { + tool.isEnabled = v; + toolDiv.style.opacity = v ? '1' : '0.5'; + tg.setTooltip(v ? 'Выключить инструмент' : 'Включить инструмент'); + await this.plugin.saveSettings(); + await this.plugin.syncSettings(); // Мгновенно синхроним с бэкендом + }) + ); + // Убираем лишние рамки и отступы у элемента Setting для компактности в шапке + toggleSetting.settingEl.style.border = 'none'; + toggleSetting.settingEl.style.padding = '0'; + toggleSetting.infoEl.remove(); + + // Описание toolDiv.createEl('div', { text: tool.originalDescription, attr: { style: 'font-size: 0.85em; color: var(--text-muted); margin-bottom: 8px;' } }); new Setting(toolDiv) - .setName('Кастомное описание (Override)') - .setDesc('Оставьте пустым, чтобы использовать оригинальное.') + .setName('Дополнительные инструкции') + .setDesc('Этот текст будет добавлен к оригинальному описанию инструмента. Оставьте пустым, если не требуется.') .addTextArea(t => { t.inputEl.style.width = '100%'; t.setValue(tool.customDescription).onChange(async v => {