From 1d28b6b1bebde1de2daa77b0804a3ca206c7bd10 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Mon, 9 Feb 2026 01:44:00 +0100 Subject: [PATCH] fix: MCP Resources Browser selection & attaching --- .../app/dialogs/DialogMcpResources.svelte | 57 +++++++++++-------- .../McpResourceBrowser.svelte | 1 - .../McpResourceBrowserServerItem.svelte | 29 ++++------ 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte b/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte index c7b372e0b3..fa336956cb 100644 --- a/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte +++ b/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte @@ -58,7 +58,8 @@ function handleResourceSelect(resource: MCPResourceInfo, shiftKey: boolean = false) { if (shiftKey && lastSelectedUri) { - const allResources = getAllResourcesFlat(); + // Get all resources in tree order (matching the display order in McpResourceBrowser) + const allResources = getAllResourcesFlatInTreeOrder(); const lastIndex = allResources.findIndex((r) => r.uri === lastSelectedUri); const currentIndex = allResources.findIndex((r) => r.uri === resource.uri); @@ -87,7 +88,20 @@ lastSelectedUri = resource.uri; } - function getAllResourcesFlat(): MCPResourceInfo[] { + function getResourceDisplayName(resource: MCPResourceInfo): string { + // Extract the display name from the resource URI (last path segment) + try { + const uriWithoutProtocol = resource.uri.replace(/^[a-z]+:\/\//, ''); + const parts = uriWithoutProtocol.split('/'); + return parts[parts.length - 1] || resource.name || resource.uri; + } catch { + return resource.name || resource.uri; + } + } + + function getAllResourcesFlatInTreeOrder(): MCPResourceInfo[] { + // Get resources in the same order as displayed in McpResourceBrowser tree + // Sort by: folders first (if applicable), then alphabetically by display name const allResources: MCPResourceInfo[] = []; const resourcesMap = mcpResources(); @@ -97,7 +111,17 @@ } } - return allResources; + // Sort to match tree display order: folders first, then alphabetically + return allResources.sort((a, b) => { + const aName = getResourceDisplayName(a); + const bName = getResourceDisplayName(b); + return aName.localeCompare(bName); + }); + } + + function getAllResourcesFlat(): MCPResourceInfo[] { + // Fallback for other uses (like attaching) + return getAllResourcesFlatInTreeOrder(); } async function handleAttach() { @@ -129,27 +153,11 @@ isAttaching = false; } } - - async function handleQuickAttach(resource: MCPResourceInfo) { - isAttaching = true; - - try { - await mcpStore.attachResource(resource.uri); - - onAttach?.(resource); - - toast.success(`Resource attached: ${resource.name}`); - } catch (error) { - console.error('Failed to attach resource:', error); - } finally { - isAttaching = false; - } - } - + @@ -165,18 +173,17 @@ -
-
+
+
-
+
{#if selectedResources.size === 1} {@const allResources = getAllResourcesFlat()} {@const selectedResource = allResources.find((r) => selectedResources.has(r.uri))} @@ -194,7 +201,7 @@
- + - {/if}
{/if} @@ -144,6 +135,7 @@ {:else} {/if} + {#if favicon} {/if} + {displayName} + ({serverRes.resources.length}) + {#if serverRes.loading} {/if}