import { App, PostMessageTransport } from "../src/app.js"; import { McpUiToolInputNotificationSchema, McpUiSizeChangeNotificationSchema, McpUiToolResultNotificationSchema, } from "../src/types.js"; window.addEventListener("load", async () => { const root = document.getElementById("root")!; const appendText = (textContent: string, opts = {}) => { root.appendChild( Object.assign(document.createElement("div"), { textContent, ...opts, }), ); }; const appendError = (error: unknown) => appendText( `Error: ${error instanceof Error ? error.message : String(error)}`, { style: "color: red;" }, ); const transport = new PostMessageTransport(window.parent); const app = new App({ name: "MCP UI Client", version: "1.0.0", }); app.setNotificationHandler( McpUiToolResultNotificationSchema, async ({ params: { content, structuredContent, isError } }) => { appendText( `Tool call result received: isError=${isError}, content=${content}, structuredContent=${JSON.stringify(structuredContent)}`, ); }, ); app.setNotificationHandler( McpUiSizeChangeNotificationSchema, async ({ params: { width, height } }) => { appendText( `Size change notification received: width=${width}, height=${height}`, ); }, ); app.setNotificationHandler( McpUiToolInputNotificationSchema, async ({ params }) => { appendText( `Tool call input received: ${JSON.stringify(params.arguments)}`, ); }, ); document.body.addEventListener("resize", () => { app.sendSizeChange({ width: document.body.scrollWidth, height: document.body.scrollHeight, }); }); root.appendChild( Object.assign(document.createElement("button"), { textContent: "Get Weather (Tool)", onclick: async () => { const signal = AbortSignal.timeout(5000); try { const result = await app.callServerTool({ name: "get-weather", arguments: { location: "Tokyo" }, }); appendText(`Weather tool result: ${JSON.stringify(result)}`); } catch (e) { appendError(e); } }, }), ); root.appendChild( Object.assign(document.createElement("button"), { textContent: "Notify Cart Updated", onclick: async () => { try { await app.sendLog({ level: "info", data: "cart-updated", }); } catch (e) { appendError(e); } }, }), ); root.appendChild( Object.assign(document.createElement("button"), { textContent: "Prompt Weather in Tokyo", onclick: async () => { const signal = AbortSignal.timeout(5000); try { const { isError } = await app.sendMessage( { role: "user", // Forced. content: [ { type: "text", text: "What is the weather in Tokyo?", }, ], }, { signal }, ); appendText(`Prompt result: ${isError ? "error" : "success"}`); } catch (e) { if (signal.aborted) { appendError("Prompt request timed out"); return; } appendError(e); } }, }), ); root.appendChild( Object.assign(document.createElement("button"), { textContent: "Open Link to Google", onclick: async () => { try { const { isError } = await app.sendOpenLink({ url: "https://www.google.com", }); appendText(`Open link result: ${isError ? "error" : "success"}`); } catch (e) { appendError(e); } }, }), ); await app.connect(transport); });