import { useState, useCallback } from "react"; import { createRoot } from "react-dom/client"; import { useApp } from "../src/react/useApp"; import type { CallToolResult, Implementation, } from "@modelcontextprotocol/sdk/types.js"; import { McpUiSizeChangeNotificationSchema, McpUiToolResultNotificationSchema, } from "../src/types"; const APP_INFO: Implementation = { name: "MCP UI React Example Client", version: "1.0.0", protocolVersion: "2025-06-18", }; export function McpClientApp() { const [toolResults, setToolResults] = useState([]); const [messages, setMessages] = useState([]); const { app, isConnected, error } = useApp({ appInfo: APP_INFO, capabilities: {}, onAppCreated: (app) => { app.setNotificationHandler( McpUiToolResultNotificationSchema, async (notification) => { setToolResults((prev) => [...prev, notification.params]); }, ); app.setNotificationHandler( McpUiSizeChangeNotificationSchema, async (notification) => { document.body.style.width = `${notification.params.width}px`; document.body.style.height = `${notification.params.height}px`; }, ); }, }); const handleGetWeather = useCallback(async () => { if (!app) return; try { const result = await app.callServerTool({ name: "get-weather", arguments: { city: "Tokyo" }, }); setMessages((prev) => [ ...prev, `Weather tool result: ${JSON.stringify(result)}`, ]); } catch (e) { setMessages((prev) => [...prev, `Tool call error: ${e}`]); } }, [app]); const handleNotifyCart = useCallback(async () => { if (!app) return; await app.sendLog({ level: "info", data: "cart-updated" }); setMessages((prev) => [...prev, "Notification sent: cart-updated"]); }, [app]); const handlePromptWeather = useCallback(async () => { if (!app) return; const signal = AbortSignal.timeout(5000); try { const { isError } = await app.sendMessage( { role: "user", content: [ { type: "text", text: "What is the weather in Tokyo?", }, ], }, { signal }, ); setMessages((prev) => [ ...prev, `Prompt result: ${isError ? "error" : "success"}`, ]); } catch (e) { if (signal.aborted) { setMessages((prev) => [...prev, "Prompt request timed out"]); return; } setMessages((prev) => [...prev, `Prompt error: ${e}`]); } }, [app]); const handleOpenLink = useCallback(async () => { if (!app) return; const { isError } = await app.sendOpenLink({ url: "https://www.google.com", }); setMessages((prev) => [ ...prev, `Open link result: ${isError ? "error" : "success"}`, ]); }, [app]); if (error) { return (
Error connecting: {error.message}
); } if (!isConnected) { return
Connecting...
; } return (

MCP UI Client (React)

{toolResults.length > 0 && (

Tool Results:

{toolResults.map((result, i) => (
isError: {String(result.isError ?? false)}
content: {JSON.stringify(result.content)}
{result.structuredContent && ( <> structuredContent:{" "} {JSON.stringify(result.structuredContent)} )}
))}
)} {messages.length > 0 && (

Messages:

{messages.map((msg, i) => (
{msg}
))}
)}
); } window.addEventListener("load", () => { const root = document.getElementById("root"); if (!root) { throw new Error("Root element not found"); } createRoot(root).render(); });