From 6f1d1a07f2649efd188b7dd8e4bbdfa9fff30160 Mon Sep 17 00:00:00 2001 From: Anes Hadrez Date: Fri, 6 Feb 2026 17:31:22 +0300 Subject: [PATCH 1/4] feat: add tool_ids support for Open WebUI MCP tools Pass tool_ids as a URL query parameter (comma-separated) to include Open WebUI tool IDs (e.g. MCP servers) in chat completion requests. This enables MCP tool activation when the widget is embedded. Co-Authored-By: Claude Opus 4.6 --- src/lib/ChatWidget.svelte | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/lib/ChatWidget.svelte b/src/lib/ChatWidget.svelte index efbd728..9d4320d 100644 --- a/src/lib/ChatWidget.svelte +++ b/src/lib/ChatWidget.svelte @@ -12,6 +12,7 @@ let apiKey: string = ''; let model = $state('gpt-4o-mini'); // default fallback let endpoint: string = '/api/chat/completions'; // relative to current host by default + let toolIds: string[] = []; // Open WebUI tool IDs (e.g. MCP servers) // Configure marked for secure rendering marked.setOptions({ @@ -33,12 +34,14 @@ const qsModel = qs.get('model'); const qsEndpoint = qs.get('endpoint'); + const qsToolIds = qs.get('tool_ids'); + if (qsApiKey !== null) apiKey = qsApiKey; if (qsModel !== null) model = qsModel; if (qsEndpoint !== null) endpoint = qsEndpoint; - // Default values are already set if query params are null + if (qsToolIds !== null) toolIds = qsToolIds.split(',').filter(Boolean); - console.log('Query parameters processed:', { apiKey, model, endpoint }); + console.log('Query parameters processed:', { apiKey, model, endpoint, toolIds }); } catch (e) { console.error('Error processing query parameters in onMount:', e); } @@ -72,7 +75,8 @@ }, body: JSON.stringify({ model, - messages: [{ role: 'user', content: text }] + messages: [{ role: 'user', content: text }], + ...(toolIds.length > 0 && { tool_ids: toolIds }) }) }); const data = await res.json(); From 6257e3dccaa34000f3a2f3e6ace7ebc9a377d810 Mon Sep 17 00:00:00 2001 From: Anes Hadrez Date: Tue, 10 Feb 2026 00:28:37 +0300 Subject: [PATCH 2/4] feat: switch to streaming for MCP tool support The non-streaming /api/chat/completions endpoint doesn't execute Open WebUI's MCP tool pipeline. Streaming mode enables tool context injection and provides real-time response rendering. Co-Authored-By: Claude Opus 4.6 --- src/lib/ChatWidget.svelte | 53 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/lib/ChatWidget.svelte b/src/lib/ChatWidget.svelte index 9d4320d..7a2cbfc 100644 --- a/src/lib/ChatWidget.svelte +++ b/src/lib/ChatWidget.svelte @@ -76,12 +76,59 @@ body: JSON.stringify({ model, messages: [{ role: 'user', content: text }], + stream: true, ...(toolIds.length > 0 && { tool_ids: toolIds }) }) }); - const data = await res.json(); - const reply = data?.choices?.[0]?.message?.content ?? '⚠️ Error retrieving response'; - messages = [...messages, { role: 'assistant', content: reply }]; + + if (!res.ok) { + messages = [...messages, { role: 'assistant', content: '⚠️ Error retrieving response' }]; + return; + } + + // Stream the response + const reader = res.body?.getReader(); + if (!reader) { + messages = [...messages, { role: 'assistant', content: '⚠️ Error retrieving response' }]; + return; + } + + const decoder = new TextDecoder(); + let assistantContent = ''; + messages = [...messages, { role: 'assistant', content: '' }]; + isLoading = false; // hide loading dots, show streaming text + + let buffer = ''; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() ?? ''; + + for (const line of lines) { + if (!line.startsWith('data: ')) continue; + const data = line.slice(6).trim(); + if (data === '[DONE]') continue; + + try { + const parsed = JSON.parse(data); + const delta = parsed?.choices?.[0]?.delta?.content; + if (delta) { + assistantContent += delta; + messages = [...messages.slice(0, -1), { role: 'assistant', content: assistantContent }]; + } + } catch { + // skip non-JSON lines (e.g. sources/tool results) + } + } + } + + // If nothing was streamed, show error + if (!assistantContent) { + messages = [...messages.slice(0, -1), { role: 'assistant', content: '⚠️ Error retrieving response' }]; + } } catch (err) { messages = [...messages, { role: 'assistant', content: '⚠️ Network error' }]; } finally { From 8f2ef6a3a5e3932bee7249a3e71c69d55a2d76c2 Mon Sep 17 00:00:00 2001 From: Anes Hadrez Date: Wed, 11 Feb 2026 21:26:03 +0300 Subject: [PATCH 3/4] feat: add welcome screen, conversation context, and UX improvements - Fix conversation context bug: send full message history instead of only last message - Add welcome screen with icon, title, subtitle, and 3 suggested prompts - Add configurable title via 'title' URL param (defaults to 'GCP Cost Assistant') - Add 'New chat' button to clear conversation - Switch to Google Blue (#4285f4) color scheme - Styled send button with blue background - Better placeholder: 'Ask about GCP costs and pricing...' - Chat bubble icon instead of layers icon Co-Authored-By: Claude Opus 4.6 --- src/lib/ChatWidget.svelte | 342 +++++++++++++++++++++++++------------- 1 file changed, 224 insertions(+), 118 deletions(-) diff --git a/src/lib/ChatWidget.svelte b/src/lib/ChatWidget.svelte index 7a2cbfc..42b47b1 100644 --- a/src/lib/ChatWidget.svelte +++ b/src/lib/ChatWidget.svelte @@ -1,5 +1,5 @@