From 66b1b7344840d1b880c65e0d5833082a8d9f5d54 Mon Sep 17 00:00:00 2001 From: = <1936278+evalstate@users.noreply.github.com> Date: Sun, 1 Dec 2024 10:24:12 +0000 Subject: [PATCH 1/4] Render HTML5 Audio Player if Tool Result resource mimetype is audio. --- client/src/components/ToolsTab.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index 7b85ccc..1645422 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -83,9 +83,19 @@ const ToolsTab = ({ /> )} {item.type === "resource" && ( -
-                  {JSON.stringify(item.resource, null, 2)}
-                
+ item.resource?.mimeType?.startsWith("audio/") ? ( + + ) : ( +
+                    {JSON.stringify(item.resource, null, 2)}
+                  
+ ) )} ))} From 068d21387a237c346a3cf6155e9e583990ce0e0e Mon Sep 17 00:00:00 2001 From: = <1936278+evalstate@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:47:50 +0000 Subject: [PATCH 2/4] extended type for "audio" update to spec --- client/src/components/ToolsTab.tsx | 41 ++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index 1645422..bea46a5 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -7,13 +7,41 @@ import { Textarea } from "@/components/ui/textarea"; import { ListToolsResult, Tool, - CallToolResultSchema, + TextContentSchema, + ImageContentSchema, + ResultSchema, + EmbeddedResourceSchema, } from "@modelcontextprotocol/sdk/types.js"; import { AlertCircle, Send } from "lucide-react"; import { useState } from "react"; import ListPane from "./ListPane"; import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { z } from "zod"; + +// Define the AudioContent schema +export const AudioContentSchema = z.object({ + type: z.literal("audio"), + data: z.string().base64(), + mimeType: z.string(), +}).passthrough(); + +// Extend the CallToolResult schema to include audio content +export const ExtendedCallToolResultSchema = ResultSchema.extend({ + content: z.array( + z.discriminatedUnion("type", [ + TextContentSchema, + ImageContentSchema, + AudioContentSchema, + EmbeddedResourceSchema, + ]) + ), + isError: z.boolean().default(false).optional(), +}); + +// Export the types +export type AudioContent = z.infer; +export type ExtendedCallToolResult = z.infer; const ToolsTab = ({ tools, @@ -40,7 +68,7 @@ const ToolsTab = ({ if (!toolResult) return null; if ("content" in toolResult) { - const parsedResult = CallToolResultSchema.safeParse(toolResult); + const parsedResult = ExtendedCallToolResultSchema.safeParse(toolResult); if (!parsedResult.success) { return ( <> @@ -82,6 +110,15 @@ const ToolsTab = ({ className="max-w-full h-auto" /> )} + {item.type === "audio" && ( + + )} {item.type === "resource" && ( item.resource?.mimeType?.startsWith("audio/") ? ( )} - {item.type === "resource" && ( - item.resource?.mimeType?.startsWith("audio/") ? ( + {item.type === "resource" && + (item.resource?.mimeType?.startsWith("audio/") ? (