diff --git a/tools/server/public/index.html.gz b/tools/server/public/index.html.gz index 20523afa33..ea4e6ed8ab 100644 Binary files a/tools/server/public/index.html.gz and b/tools/server/public/index.html.gz differ diff --git a/tools/server/webui/src/lib/constants/localstorage-keys.ts b/tools/server/webui/src/lib/constants/localstorage-keys.ts index 6b9a9e0e2f..dc4d69b4ec 100644 --- a/tools/server/webui/src/lib/constants/localstorage-keys.ts +++ b/tools/server/webui/src/lib/constants/localstorage-keys.ts @@ -1,3 +1,4 @@ export const CONFIG_LOCALSTORAGE_KEY = 'LlamaCppWebui.config'; export const USER_OVERRIDES_LOCALSTORAGE_KEY = 'LlamaCppWebui.userOverrides'; export const FAVOURITE_MODELS_LOCALSTORAGE_KEY = 'LlamaCppWebui.favouriteModels'; +export const MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY = 'LlamaCppWebui.mcpDefaultEnabled'; diff --git a/tools/server/webui/src/lib/stores/conversations.svelte.ts b/tools/server/webui/src/lib/stores/conversations.svelte.ts index 39f206479f..3cfbd3d1c9 100644 --- a/tools/server/webui/src/lib/stores/conversations.svelte.ts +++ b/tools/server/webui/src/lib/stores/conversations.svelte.ts @@ -36,7 +36,8 @@ import { ISO_TIME_SEPARATOR, ISO_TIME_SEPARATOR_REPLACEMENT, NON_ALPHANUMERIC_REGEX, - MULTIPLE_UNDERSCORE_REGEX + MULTIPLE_UNDERSCORE_REGEX, + MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY } from '$lib/constants'; class ConversationsStore { @@ -61,7 +62,37 @@ class ConversationsStore { isInitialized = $state(false); /** Pending MCP server overrides for new conversations (before first message) */ - pendingMcpServerOverrides = $state([]); + pendingMcpServerOverrides = $state(ConversationsStore.loadMcpDefaults()); + + /** Load MCP default overrides from localStorage */ + private static loadMcpDefaults(): McpServerOverride[] { + if (typeof globalThis.localStorage === 'undefined') return []; + try { + const raw = localStorage.getItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY); + if (!raw) return []; + const parsed = JSON.parse(raw); + if (!Array.isArray(parsed)) return []; + return parsed.filter( + (o: unknown) => typeof o === 'object' && o !== null && 'serverId' in o && 'enabled' in o + ) as McpServerOverride[]; + } catch { + return []; + } + } + + /** Persist MCP default overrides to localStorage */ + private saveMcpDefaults(): void { + if (typeof globalThis.localStorage === 'undefined') return; + const plain = this.pendingMcpServerOverrides.map((o) => ({ + serverId: o.serverId, + enabled: o.enabled + })); + if (plain.length > 0) { + localStorage.setItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY, JSON.stringify(plain)); + } else { + localStorage.removeItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY); + } + } /** Callback for title update confirmation dialog */ titleUpdateConfirmationCallback?: (currentTitle: string, newTitle: string) => Promise; @@ -261,6 +292,8 @@ class ConversationsStore { clearActiveConversation(): void { this.activeConversation = null; this.activeMessages = []; + // reload MCP defaults so new chats inherit persisted state + this.pendingMcpServerOverrides = ConversationsStore.loadMcpDefaults(); } /** @@ -597,6 +630,7 @@ class ConversationsStore { this.pendingMcpServerOverrides = [...this.pendingMcpServerOverrides, { serverId, enabled }]; } } + this.saveMcpDefaults(); } /** @@ -621,6 +655,7 @@ class ConversationsStore { */ clearPendingMcpServerOverrides(): void { this.pendingMcpServerOverrides = []; + this.saveMcpDefaults(); } /** diff --git a/tools/server/webui/src/lib/stores/mcp.svelte.ts b/tools/server/webui/src/lib/stores/mcp.svelte.ts index dadf8fda62..efc8cf060e 100644 --- a/tools/server/webui/src/lib/stores/mcp.svelte.ts +++ b/tools/server/webui/src/lib/stores/mcp.svelte.ts @@ -208,23 +208,16 @@ class MCPStore { } /** - * Checks if a server is enabled, considering per-chat overrides. + * Checks if a server is enabled for a given chat. + * Only per-chat overrides (persisted in localStorage for new chats, + * or in IndexedDB for existing conversations) control enabled state. */ #checkServerEnabled( server: MCPServerSettingsEntry, perChatOverrides?: McpServerOverride[] ): boolean { - if (!server.enabled) { - return false; - } - - if (perChatOverrides) { - const override = perChatOverrides.find((o) => o.serverId === server.id); - - return override?.enabled ?? false; - } - - return false; + const override = perChatOverrides?.find((o) => o.serverId === server.id); + return override?.enabled ?? false; } /** @@ -570,18 +563,8 @@ class MCPStore { getEnabledServersForConversation( perChatOverrides?: McpServerOverride[] ): MCPServerSettingsEntry[] { - if (!perChatOverrides?.length) { - return []; - } - return this.getServers().filter((server) => { - if (!server.enabled) { - return false; - } - - const override = perChatOverrides.find((o) => o.serverId === server.id); - - return override?.enabled ?? false; + return this.#checkServerEnabled(server, perChatOverrides); }); }