diff --git a/src/lib/components/mcp/AddServerForm.svelte b/src/lib/components/mcp/AddServerForm.svelte index a5bc035d5bf..faea7dace05 100644 --- a/src/lib/components/mcp/AddServerForm.svelte +++ b/src/lib/components/mcp/AddServerForm.svelte @@ -1,5 +1,5 @@
+ + {#if initialDescription} +

{initialDescription}

+ {/if} +
diff --git a/src/lib/components/mcp/MCPServerManager.svelte b/src/lib/components/mcp/MCPServerManager.svelte index 68d7dd69fa3..a0785ec9078 100644 --- a/src/lib/components/mcp/MCPServerManager.svelte +++ b/src/lib/components/mcp/MCPServerManager.svelte @@ -3,15 +3,17 @@ import Modal from "$lib/components/Modal.svelte"; import ServerCard from "./ServerCard.svelte"; import AddServerForm from "./AddServerForm.svelte"; + import MCPServerSearch from "./MCPServerSearch.svelte"; import { allMcpServers, selectedServerIds, enabledServersCount, addCustomServer, + updateCustomServer, refreshMcpServers, healthCheckServer, } from "$lib/stores/mcpServers"; - import type { KeyValuePair } from "$lib/types/Tool"; + import type { KeyValuePair, MCPRegistryEntry, MCPServer } from "$lib/types/Tool"; import IconAddLarge from "~icons/carbon/add-large"; import IconRefresh from "~icons/carbon/renew"; import LucideHammer from "~icons/lucide/hammer"; @@ -26,22 +28,74 @@ let { onclose }: Props = $props(); type View = "list" | "add"; + type AddTab = "search" | "manual"; + let currentView = $state("list"); + let addTab = $state("search"); let isRefreshing = $state(false); + let prefillName = $state(""); + let prefillUrl = $state(""); + let prefillDescription = $state(""); + let prefillHeaders = $state([]); + let editingServer = $state(null); + const baseServers = $derived($allMcpServers.filter((s) => s.type === "base")); const customServers = $derived($allMcpServers.filter((s) => s.type === "custom")); const enabledCount = $derived($enabledServersCount); function handleAddServer(serverData: { name: string; url: string; headers?: KeyValuePair[] }) { - addCustomServer(serverData); + if (editingServer) { + updateCustomServer(editingServer.id, serverData); + } else { + addCustomServer(serverData); + } + resetAddState(); currentView = "list"; } + function resetAddState() { + prefillName = ""; + prefillUrl = ""; + prefillDescription = ""; + prefillHeaders = []; + editingServer = null; + addTab = "search"; + } + function handleCancel() { + resetAddState(); currentView = "list"; } + function handleEditServer(server: MCPServer) { + editingServer = server; + prefillName = server.name; + prefillUrl = server.url; + prefillDescription = ""; + prefillHeaders = server.headers ?? []; + addTab = "manual"; + currentView = "add"; + } + + function handleRegistryAdd(entry: MCPRegistryEntry) { + prefillName = entry.title ?? entry.name; + prefillUrl = entry.url; + prefillDescription = entry.description; + prefillHeaders = (entry.requiredHeaders ?? []).map((h) => ({ + key: h.name, + value: "", + description: h.description, + required: true, + })); + addTab = "manual"; + } + + function switchToAdd() { + resetAddState(); + currentView = "add"; + } + async function handleRefresh() { if (isRefreshing) return; isRefreshing = true; @@ -63,6 +117,8 @@

{#if currentView === "list"} MCP Servers + {:else if editingServer} + Edit MCP server {:else} Add MCP server {/if} @@ -70,8 +126,10 @@

{#if currentView === "list"} Manage MCP servers to extend {publicConfig.PUBLIC_APP_NAME} with external tools. + {:else if editingServer} + Update the configuration for {editingServer.name}. {:else} - Add a custom MCP server to {publicConfig.PUBLIC_APP_NAME}. + Search the MCP Registry or add a custom server URL. {/if}

@@ -93,7 +151,7 @@

{$allMcpServers.length} - {$allMcpServers.length === 1 ? "server" : "servers"} configured + {$allMcpServers.length > 1 ? "servers" : "server"} configured

{enabledCount} enabled @@ -102,17 +160,19 @@

+ {#if $allMcpServers.length > 0} + + {/if} -
{:else if currentView === "add"} - + +
+ + +
+ + {#if addTab === "search"} + +
+ +
+ {:else} + + {/if} {/if} diff --git a/src/lib/components/mcp/MCPServerSearch.svelte b/src/lib/components/mcp/MCPServerSearch.svelte new file mode 100644 index 00000000000..923c560d82f --- /dev/null +++ b/src/lib/components/mcp/MCPServerSearch.svelte @@ -0,0 +1,95 @@ + + +
+ +
+ + +
+ + + {#if loading} +
+ Searching registry… +
+ {:else if error} +
+

+ Registry unavailable: {error} +

+
+ {:else if results.length === 0 && query} +
+ No servers found for "{query}". Try the Manual tab to add a custom URL. +
+ {:else} +
+ {#each results as entry (entry.name)} + + {/each} +
+ {/if} +
diff --git a/src/lib/components/mcp/RegistryResultCard.svelte b/src/lib/components/mcp/RegistryResultCard.svelte new file mode 100644 index 00000000000..74a96e30120 --- /dev/null +++ b/src/lib/components/mcp/RegistryResultCard.svelte @@ -0,0 +1,66 @@ + + +
+ + {#if entry.icons?.[0]?.src} + {entry.name} + {:else} +
+ +
+ {/if} + +
+ + + {entry.title ?? entry.name} + + + +

+ {entry.description} +

+
+ + +
+ {#if alreadyAdded} + + + Added + + {:else} + + {/if} +
+
diff --git a/src/lib/components/mcp/ServerCard.svelte b/src/lib/components/mcp/ServerCard.svelte index 694cd1ee803..19bb6643333 100644 --- a/src/lib/components/mcp/ServerCard.svelte +++ b/src/lib/components/mcp/ServerCard.svelte @@ -1,6 +1,7 @@