* wip: server_tools * feat: Integrate with `/tools` endpoint * feat: Builtin + MCP + JSON Schema Tools WIP * refactor * displayName -> display_name * snake_case everywhere * rm redundant field * feat: Improvements * chore: update webui build output * refactor: Updates after server updates * chore: update webui build output * change arg to --tools all * feat: UI improvements * chore: update webui build output * add readme mention * llama-gen-docs * chore: update webui build output * chore: update webui build output * chore: update webui build output * feat: Reorganize settings sections * feat: Separate dialogs for MCP Servers Settings and Import/Export * feat: WIP * feat: WIP * feat: WIP * feat: WIP * feat: WIP * feat: WIP * WIP on allozaur/20677-webui-server-tools * feat: UI improvements * chore: Update package lock * chore: Run `npm audit fix` * feat: UI WIP * feat: UI * refactor: Desktop Icon Strip DRY * feat: Cleaner rendering and transition for ChatScreen * feat: UI improvements * feat: UI improvement * feat: Remove MCP Server "enable" switch from Tools submenu * chore: Run `npm audit fix` * feat: WIP * feat: Logic improvements * refactor: Cleanup * refactor: DRY * test: Fix Chat Sidebar UI Tests * chore: Update package lock * refactor: Cleanup * feat: Chat Message Action Card with Continue and Permission flow implementations * feat: Add agentic steering messages, draft messages and improve chat UX * fix: Search results UI * test: Fix unit test * feat: UI/UX improvements * refactor: Simplify `useToolsPanel` access in components * feat: Implement Processing Info Context API * feat: Implement 'Go back to chat' functionality for settings * feat: Enhance MCP Server management in Chat Form Attachments * style: Minor UI and branding adjustments * chore: Update webui static build output * chore: Formatting, linting & type checks * feat: Draft messages logic * feat: UI improvements * feat: Steering Messages improvements * refactor: Cleanup * refactor: Cleanup * feat: Improve UI * refactor: Settings navigation hook * refactor: DRY code * refactor: DRY ChatMessageUser UI components * refactor: Desktop Icon Strip DRY * refactor: Tools & permissions * fix: Navigation condition * refactor: Cleanup * refactor: Cleanup * refactor: Cleanup * fix: preserve reasoning_content in agentic flow --------- Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
110 lines
3.2 KiB
Svelte
110 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import { Plus } from '@lucide/svelte';
|
|
import { Button } from '$lib/components/ui/button';
|
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
|
import { conversationsStore } from '$lib/stores/conversations.svelte';
|
|
import { toolsStore } from '$lib/stores/tools.svelte';
|
|
import { McpServerCard, McpServerCardSkeleton } from '$lib/components/app/mcp';
|
|
import { DialogMcpServerAddNew } from '$lib/components/app/dialogs';
|
|
import { HealthCheckStatus } from '$lib/enums';
|
|
import { fade } from 'svelte/transition';
|
|
import { onMount } from 'svelte';
|
|
import McpLogo from '../mcp/McpLogo.svelte';
|
|
import { page } from '$app/state';
|
|
import { replaceState } from '$app/navigation';
|
|
|
|
interface Props {
|
|
class?: string;
|
|
}
|
|
|
|
let { class: className }: Props = $props();
|
|
|
|
let servers = $derived(mcpStore.getServersSorted());
|
|
|
|
let initialLoadComplete = $state(false);
|
|
let isAddingServer = $state(false);
|
|
|
|
onMount(() => {
|
|
if (page.url.searchParams.has('add')) {
|
|
isAddingServer = true;
|
|
|
|
const newUrl = new URL(page.url);
|
|
newUrl.searchParams.delete('add');
|
|
|
|
replaceState(newUrl, {});
|
|
}
|
|
});
|
|
|
|
$effect(() => {
|
|
if (initialLoadComplete) return;
|
|
|
|
const allChecked =
|
|
servers.length > 0 &&
|
|
servers.every((server) => {
|
|
const state = mcpStore.getHealthCheckState(server.id);
|
|
|
|
return (
|
|
state.status === HealthCheckStatus.SUCCESS || state.status === HealthCheckStatus.ERROR
|
|
);
|
|
});
|
|
|
|
if (allChecked) {
|
|
initialLoadComplete = true;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div in:fade={{ duration: 150 }} class="max-h-full overflow-auto">
|
|
<div class="flex items-center gap-2 p-4 md:absolute md:top-8 md:left-8 md:px-0 md:py-2">
|
|
<McpLogo class="h-5 w-5 md:h-6 md:w-6" />
|
|
|
|
<h1 class="text-xl font-semibold md:text-2xl">MCP Servers</h1>
|
|
</div>
|
|
|
|
<div class="sticky top-0 z-10 mt-4 flex items-start justify-end gap-4 px-8 py-4">
|
|
<Button variant="outline" size="sm" class="shrink-0" onclick={() => (isAddingServer = true)}>
|
|
<Plus class="h-4 w-4" />
|
|
|
|
Add New Server
|
|
</Button>
|
|
</div>
|
|
|
|
<DialogMcpServerAddNew bind:open={isAddingServer} />
|
|
|
|
<div class="grid gap-5 md:space-y-4 {className}">
|
|
{#if servers.length === 0 && !isAddingServer}
|
|
<div class="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
|
|
No MCP Servers configured yet. Add one to enable agentic features.
|
|
</div>
|
|
{/if}
|
|
|
|
{#if servers.length > 0}
|
|
<div
|
|
class="grid gap-3"
|
|
style="grid-template-columns: repeat(auto-fill, minmax(min(32rem, calc(100dvw - 2rem)), 1fr));"
|
|
>
|
|
{#each servers as server (server.id)}
|
|
{#if !initialLoadComplete}
|
|
<McpServerCardSkeleton />
|
|
{:else}
|
|
<McpServerCard
|
|
{server}
|
|
faviconUrl={mcpStore.getServerFavicon(server.id)}
|
|
enabled={conversationsStore.isMcpServerEnabledForChat(server.id)}
|
|
onToggle={async () => {
|
|
const wasEnabled = conversationsStore.isMcpServerEnabledForChat(server.id);
|
|
await conversationsStore.toggleMcpServerForChat(server.id);
|
|
if (!wasEnabled) {
|
|
toolsStore.enableAllToolsForServer(server.id);
|
|
}
|
|
}}
|
|
onUpdate={(updates) => mcpStore.updateServer(server.id, updates)}
|
|
onDelete={() => mcpStore.removeServer(server.id)}
|
|
/>
|
|
{/if}
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|