diff --git a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentPreview.svelte b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentPreview.svelte
index 0b0bf52ad9..f05bdd8a03 100644
--- a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentPreview.svelte
+++ b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentPreview.svelte
@@ -8,7 +8,8 @@
isImageFile,
isPdfFile,
isAudioFile,
- getLanguageFromFilename
+ getLanguageFromFilename,
+ createBase64DataUrl
} from '$lib/utils';
import { convertPDFToImage } from '$lib/utils/browser-only';
import { modelsStore } from '$lib/stores/models.svelte';
@@ -255,7 +256,7 @@
diff --git a/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte b/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte
index e5f7d894f0..a0bc97a5cc 100644
--- a/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte
+++ b/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte
@@ -3,7 +3,8 @@
import { Button } from '$lib/components/ui/button';
import { cn } from '$lib/components/ui/utils';
import { mcpStore } from '$lib/stores/mcp.svelte';
- import { isImageMimeType } from '$lib/utils';
+ import { isImageMimeType, createBase64DataUrl } from '$lib/utils';
+ import { MimeTypeApplication } from '$lib/enums';
import { ActionIconCopyToClipboard } from '$lib/components/app';
import type { MCPResourceInfo, MCPResourceContent } from '$lib/types';
@@ -135,9 +136,12 @@
{/if}
{#each blobContent as blob (blob.uri)}
- {#if isImageMimeType(blob.mimeType)}
+ {#if isImageMimeType(blob.mimeType ?? MimeTypeApplication.OCTET_STREAM)}
diff --git a/tools/server/webui/src/lib/enums/files.ts b/tools/server/webui/src/lib/enums/files.ts
index 3b226b4862..84f90b3ea6 100644
--- a/tools/server/webui/src/lib/enums/files.ts
+++ b/tools/server/webui/src/lib/enums/files.ts
@@ -163,7 +163,8 @@ export enum UriPattern {
// MIME type enums
export enum MimeTypeApplication {
- PDF = 'application/pdf'
+ PDF = 'application/pdf',
+ OCTET_STREAM = 'application/octet-stream'
}
export enum MimeTypeAudio {
diff --git a/tools/server/webui/src/lib/services/mcp.service.ts b/tools/server/webui/src/lib/services/mcp.service.ts
index 6a1ac97111..c465d5055e 100644
--- a/tools/server/webui/src/lib/services/mcp.service.ts
+++ b/tools/server/webui/src/lib/services/mcp.service.ts
@@ -10,7 +10,7 @@
* NO business logic, NO state management, NO orchestration.
* This is the protocol layer - pure MCP SDK operations.
*
- * @see MCPClient in clients/mcp/ for business logic facade
+ * @see mcpStore in stores/mcp.svelte.ts for business logic facade
*/
import { Client } from '@modelcontextprotocol/sdk/client';
@@ -51,7 +51,7 @@ import {
DEFAULT_CLIENT_VERSION,
DEFAULT_IMAGE_MIME_TYPE
} from '$lib/constants/mcp';
-import { throwIfAborted, isAbortError } from '$lib/utils';
+import { throwIfAborted, isAbortError, createBase64DataUrl } from '$lib/utils';
import { buildProxiedUrl } from '$lib/utils/cors-proxy';
interface ToolResultContentItem {
@@ -421,7 +421,7 @@ export class MCPService {
}
if (content.type === MCPContentType.IMAGE && content.data) {
- return `data:${content.mimeType ?? DEFAULT_IMAGE_MIME_TYPE};base64,${content.data}`;
+ return createBase64DataUrl(content.mimeType ?? DEFAULT_IMAGE_MIME_TYPE, content.data);
}
if (content.type === MCPContentType.RESOURCE && content.resource) {
@@ -434,7 +434,7 @@ export class MCPService {
}
if (content.data && content.mimeType) {
- return `data:${content.mimeType};base64,${content.data}`;
+ return createBase64DataUrl(content.mimeType, content.data);
}
return JSON.stringify(content);
diff --git a/tools/server/webui/src/lib/utils/data-url.ts b/tools/server/webui/src/lib/utils/data-url.ts
new file mode 100644
index 0000000000..6f55be793d
--- /dev/null
+++ b/tools/server/webui/src/lib/utils/data-url.ts
@@ -0,0 +1,10 @@
+/**
+ * Creates a base64 data URL from MIME type and base64-encoded data.
+ *
+ * @param mimeType - The MIME type (e.g., 'image/png', 'audio/mp3')
+ * @param base64Data - The base64-encoded data
+ * @returns A data URL string in format 'data:{mimeType};base64,{data}'
+ */
+export function createBase64DataUrl(mimeType: string, base64Data: string): string {
+ return `data:${mimeType};base64,${base64Data}`;
+}
diff --git a/tools/server/webui/src/lib/utils/index.ts b/tools/server/webui/src/lib/utils/index.ts
index 96a922cbd0..45bf5a9c68 100644
--- a/tools/server/webui/src/lib/utils/index.ts
+++ b/tools/server/webui/src/lib/utils/index.ts
@@ -112,6 +112,9 @@ export {
isImageMimeType
} from './mcp';
+// Data URL utilities
+export { createBase64DataUrl } from './data-url';
+
// Header utilities
export { parseHeadersToArray, serializeHeaders } from './headers';