enabled base MCP servers by default (#2001)
Browse files
src/lib/components/chat/ChatInput.svelte
CHANGED
|
@@ -23,6 +23,7 @@
|
|
| 23 |
selectedServerIds,
|
| 24 |
allMcpServers,
|
| 25 |
toggleServer,
|
|
|
|
| 26 |
} from "$lib/stores/mcpServers";
|
| 27 |
import { getMcpServerFaviconUrl } from "$lib/utils/favicon";
|
| 28 |
import { page } from "$app/state";
|
|
@@ -437,7 +438,7 @@
|
|
| 437 |
<button
|
| 438 |
class="grid size-5 place-items-center rounded-full bg-blue-600/15 text-blue-700 transition-colors hover:bg-blue-600/25 dark:bg-blue-600/25 dark:text-blue-300 dark:hover:bg-blue-600/35"
|
| 439 |
aria-label="Disable all MCP servers"
|
| 440 |
-
onclick={() =>
|
| 441 |
type="button"
|
| 442 |
>
|
| 443 |
<CarbonClose class="size-3.5" />
|
|
|
|
| 23 |
selectedServerIds,
|
| 24 |
allMcpServers,
|
| 25 |
toggleServer,
|
| 26 |
+
disableAllServers,
|
| 27 |
} from "$lib/stores/mcpServers";
|
| 28 |
import { getMcpServerFaviconUrl } from "$lib/utils/favicon";
|
| 29 |
import { page } from "$app/state";
|
|
|
|
| 438 |
<button
|
| 439 |
class="grid size-5 place-items-center rounded-full bg-blue-600/15 text-blue-700 transition-colors hover:bg-blue-600/25 dark:bg-blue-600/25 dark:text-blue-300 dark:hover:bg-blue-600/35"
|
| 440 |
aria-label="Disable all MCP servers"
|
| 441 |
+
onclick={() => disableAllServers()}
|
| 442 |
type="button"
|
| 443 |
>
|
| 444 |
<CarbonClose class="size-3.5" />
|
src/lib/stores/mcpServers.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
| 4 |
* Stores custom servers and selection state in browser localStorage
|
| 5 |
*/
|
| 6 |
|
| 7 |
-
import { writable, derived } from "svelte/store";
|
| 8 |
import { base } from "$app/paths";
|
| 9 |
import { env as publicEnv } from "$env/dynamic/public";
|
| 10 |
import { browser } from "$app/environment";
|
|
@@ -23,6 +23,7 @@ const KEY_PREFIX = appLabel || baseLabel || "app";
|
|
| 23 |
const STORAGE_KEYS = {
|
| 24 |
CUSTOM_SERVERS: `${KEY_PREFIX}:mcp:custom-servers`,
|
| 25 |
SELECTED_IDS: `${KEY_PREFIX}:mcp:selected-ids`,
|
|
|
|
| 26 |
} as const;
|
| 27 |
|
| 28 |
// No migration needed per request — read/write only namespaced keys
|
|
@@ -76,6 +77,30 @@ function saveSelectedIds(ids: Set<string>) {
|
|
| 76 |
}
|
| 77 |
}
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
// Store for all servers (base + custom)
|
| 80 |
export const allMcpServers = writable<MCPServer[]>([]);
|
| 81 |
|
|
@@ -117,11 +142,30 @@ export async function refreshMcpServers() {
|
|
| 117 |
const merged = [...baseServers, ...customServers];
|
| 118 |
allMcpServers.set(merged);
|
| 119 |
|
| 120 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
const validIds = new Set(merged.map((s) => s.id));
|
| 122 |
-
selectedServerIds.update(($
|
| 123 |
-
const
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
});
|
| 126 |
} catch (error) {
|
| 127 |
console.error("Failed to refresh MCP servers:", error);
|
|
@@ -138,13 +182,40 @@ export function toggleServer(id: string) {
|
|
| 138 |
const newSet = new Set($ids);
|
| 139 |
if (newSet.has(id)) {
|
| 140 |
newSet.delete(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
} else {
|
| 142 |
newSet.add(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
}
|
| 144 |
return newSet;
|
| 145 |
});
|
| 146 |
}
|
| 147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
/**
|
| 149 |
* Add a custom MCP server
|
| 150 |
*/
|
|
|
|
| 4 |
* Stores custom servers and selection state in browser localStorage
|
| 5 |
*/
|
| 6 |
|
| 7 |
+
import { writable, derived, get } from "svelte/store";
|
| 8 |
import { base } from "$app/paths";
|
| 9 |
import { env as publicEnv } from "$env/dynamic/public";
|
| 10 |
import { browser } from "$app/environment";
|
|
|
|
| 23 |
const STORAGE_KEYS = {
|
| 24 |
CUSTOM_SERVERS: `${KEY_PREFIX}:mcp:custom-servers`,
|
| 25 |
SELECTED_IDS: `${KEY_PREFIX}:mcp:selected-ids`,
|
| 26 |
+
DISABLED_BASE_IDS: `${KEY_PREFIX}:mcp:disabled-base-ids`,
|
| 27 |
} as const;
|
| 28 |
|
| 29 |
// No migration needed per request — read/write only namespaced keys
|
|
|
|
| 77 |
}
|
| 78 |
}
|
| 79 |
|
| 80 |
+
// Load disabled base server IDs from localStorage (empty set if missing or on error)
|
| 81 |
+
function loadDisabledBaseIds(): Set<string> {
|
| 82 |
+
if (!browser) return new Set();
|
| 83 |
+
|
| 84 |
+
try {
|
| 85 |
+
const json = localStorage.getItem(STORAGE_KEYS.DISABLED_BASE_IDS);
|
| 86 |
+
return new Set(json ? JSON.parse(json) : []);
|
| 87 |
+
} catch (error) {
|
| 88 |
+
console.error("Failed to load disabled base MCP server IDs from localStorage:", error);
|
| 89 |
+
return new Set();
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
// Save disabled base server IDs to localStorage
|
| 94 |
+
function saveDisabledBaseIds(ids: Set<string>) {
|
| 95 |
+
if (!browser) return;
|
| 96 |
+
|
| 97 |
+
try {
|
| 98 |
+
localStorage.setItem(STORAGE_KEYS.DISABLED_BASE_IDS, JSON.stringify([...ids]));
|
| 99 |
+
} catch (error) {
|
| 100 |
+
console.error("Failed to save disabled base MCP server IDs to localStorage:", error);
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
// Store for all servers (base + custom)
|
| 105 |
export const allMcpServers = writable<MCPServer[]>([]);
|
| 106 |
|
|
|
|
| 142 |
const merged = [...baseServers, ...customServers];
|
| 143 |
allMcpServers.set(merged);
|
| 144 |
|
| 145 |
+
// Load disabled base servers
|
| 146 |
+
const disabledBaseIds = loadDisabledBaseIds();
|
| 147 |
+
|
| 148 |
+
// Auto-enable all base servers that aren't explicitly disabled
|
| 149 |
+
// Plus keep any custom servers that were previously selected
|
| 150 |
const validIds = new Set(merged.map((s) => s.id));
|
| 151 |
+
selectedServerIds.update(($currentIds) => {
|
| 152 |
+
const newSelection = new Set<string>();
|
| 153 |
+
|
| 154 |
+
// Add all base servers that aren't disabled
|
| 155 |
+
for (const server of baseServers) {
|
| 156 |
+
if (!disabledBaseIds.has(server.id)) {
|
| 157 |
+
newSelection.add(server.id);
|
| 158 |
+
}
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
// Keep custom servers that were selected and still exist
|
| 162 |
+
for (const id of $currentIds) {
|
| 163 |
+
if (validIds.has(id) && !id.startsWith("base-")) {
|
| 164 |
+
newSelection.add(id);
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
return newSelection;
|
| 169 |
});
|
| 170 |
} catch (error) {
|
| 171 |
console.error("Failed to refresh MCP servers:", error);
|
|
|
|
| 182 |
const newSet = new Set($ids);
|
| 183 |
if (newSet.has(id)) {
|
| 184 |
newSet.delete(id);
|
| 185 |
+
// Track if this is a base server being disabled
|
| 186 |
+
if (id.startsWith("base-")) {
|
| 187 |
+
const disabled = loadDisabledBaseIds();
|
| 188 |
+
disabled.add(id);
|
| 189 |
+
saveDisabledBaseIds(disabled);
|
| 190 |
+
}
|
| 191 |
} else {
|
| 192 |
newSet.add(id);
|
| 193 |
+
// Remove from disabled if re-enabling a base server
|
| 194 |
+
if (id.startsWith("base-")) {
|
| 195 |
+
const disabled = loadDisabledBaseIds();
|
| 196 |
+
disabled.delete(id);
|
| 197 |
+
saveDisabledBaseIds(disabled);
|
| 198 |
+
}
|
| 199 |
}
|
| 200 |
return newSet;
|
| 201 |
});
|
| 202 |
}
|
| 203 |
|
| 204 |
+
/**
|
| 205 |
+
* Disable all MCP servers (marks all base servers as disabled)
|
| 206 |
+
*/
|
| 207 |
+
export function disableAllServers() {
|
| 208 |
+
// Get current base server IDs and mark them all as disabled
|
| 209 |
+
const servers = get(allMcpServers);
|
| 210 |
+
const baseServerIds = servers.filter((s) => s.type === "base").map((s) => s.id);
|
| 211 |
+
|
| 212 |
+
// Save all base servers as disabled
|
| 213 |
+
saveDisabledBaseIds(new Set(baseServerIds));
|
| 214 |
+
|
| 215 |
+
// Clear the selection
|
| 216 |
+
selectedServerIds.set(new Set());
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
/**
|
| 220 |
* Add a custom MCP server
|
| 221 |
*/
|