sunpeak 0.20.23 → 0.20.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -4
- package/bin/commands/inspect.mjs +18 -0
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/embed.css +2 -0
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector/app-flatten.d.ts +7 -0
- package/dist/inspector/app-types.d.ts +83 -0
- package/dist/inspector/iframe-resource.d.ts +19 -1
- package/dist/inspector/index.cjs +3 -1
- package/dist/inspector/index.cjs.map +1 -1
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.js +3 -2
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/inline-helper-script.d.ts +22 -0
- package/dist/inspector/inspector-api.d.ts +3 -0
- package/dist/inspector/inspector.d.ts +21 -1
- package/dist/inspector/simple-sidebar.d.ts +13 -1
- package/dist/inspector/use-inspector-state.d.ts +1 -0
- package/dist/inspector/use-mcp-connection.d.ts +1 -1
- package/dist/{inspector-CJNvLoHo.js → inspector-B1355aXh.js} +393 -49
- package/dist/inspector-B1355aXh.js.map +1 -0
- package/dist/{inspector-DtEighD9.cjs → inspector-CJPO4f12.cjs} +397 -47
- package/dist/inspector-CJPO4f12.cjs.map +1 -0
- package/dist/mcp/index.cjs +1 -1
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/sandbox-proxy.html +173 -0
- package/dist/style.css +9 -1
- package/dist/types/simulation.d.ts +3 -8
- package/dist/{use-app-cSBm5Pjl.js → use-app-C2pGHlnF.js} +2 -2
- package/dist/{use-app-cSBm5Pjl.js.map → use-app-C2pGHlnF.js.map} +1 -1
- package/dist/{use-app-CxtSfkSF.cjs → use-app-DIWh7-3f.cjs} +2 -2
- package/dist/{use-app-CxtSfkSF.cjs.map → use-app-DIWh7-3f.cjs.map} +1 -1
- package/package.json +6 -3
- package/template/dist/albums/albums.html +1 -1
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +1 -1
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +1 -1
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +1 -1
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +22 -22
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-linux.png +0 -0
- package/dist/inspector-CJNvLoHo.js.map +0 -1
- package/dist/inspector-DtEighD9.cjs.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["i","J.union","J.literal","J.record","J.string","J.undefined","J.object","A","J.boolean","C","P","J.array","J.number","J.unknown","n","v","T","g","s","J.never","FJ","IJ","r","DJ","f","EJ","UJ","d","l","u","F","E","I","U","wQ","kQ","JK","eJ","t","M"],"sources":["../../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.7.1_@modelcontextprotocol+sdk@1.29.0_zod@4.4.3__react-_3f5c1a6a4033ae62a19a2bb834f0e050/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js","../src/hooks/use-host-context.ts","../src/hooks/use-tool-data.ts","../src/hooks/use-device-capabilities.ts","../src/hooks/use-display-mode.ts","../src/hooks/use-locale.ts","../src/hooks/use-platform.ts","../src/hooks/use-safe-area.ts","../src/hooks/use-styles.ts","../src/hooks/use-theme.ts","../src/hooks/use-time-zone.ts","../src/hooks/use-tool-info.ts","../src/hooks/use-user-agent.ts","../src/hooks/use-viewport.ts","../src/hooks/use-mobile.ts","../src/hooks/safe-area.tsx","../src/hooks/use-call-server-tool.ts","../src/hooks/use-create-sampling-message.ts","../src/hooks/use-download-file.ts","../src/hooks/use-list-server-resources.ts","../src/hooks/use-open-link.ts","../src/hooks/use-read-server-resource.ts","../src/hooks/use-register-tool.ts","../src/hooks/use-request-display-mode.ts","../src/hooks/use-request-teardown.ts","../src/hooks/use-send-log.ts","../src/hooks/use-send-message.ts","../src/hooks/use-send-tool-list-changed.ts","../src/hooks/use-update-model-context.ts","../src/hooks/use-host-info.ts","../src/hooks/use-teardown.ts","../src/hooks/use-app-tools.ts","../src/hooks/use-app-state.ts","../src/lib/media-queries.ts"],"sourcesContent":["var JJ=((K)=>typeof require<\"u\"?require:typeof Proxy<\"u\"?new Proxy(K,{get:(Q,X)=>(typeof require<\"u\"?require:Q)[X]}):K)(function(K){if(typeof require<\"u\")return require.apply(this,arguments);throw Error('Dynamic require of \"'+K+'\" is not supported')});import{useEffect as sJ,useState as c}from\"react\";import{mergeCapabilities as uJ}from\"@modelcontextprotocol/sdk/shared/protocol.js\";import{CallToolRequestSchema as hJ,CallToolResultSchema as mJ,CreateMessageResultSchema as cJ,CreateMessageResultWithToolsSchema as rJ,EmptyResultSchema as lJ,ListResourcesResultSchema as iJ,ListToolsRequestSchema as pJ,PingRequestSchema as nJ,ReadResourceResultSchema as oJ}from\"@modelcontextprotocol/sdk/types.js\";import{Protocol as KJ}from\"@modelcontextprotocol/sdk/shared/protocol.js\";class z extends KJ{_registeredMethods=new Set;_eventSlots=new Map;onEventDispatch(K,Q){}_ensureEventSlot(K){let Q=this._eventSlots.get(K);if(!Q){let X=this.eventSchemas[K];if(!X)throw Error(`Unknown event: ${String(K)}`);Q={listeners:[]},this._eventSlots.set(K,Q);let Y=X.shape.method.value;this._registeredMethods.add(Y);let Z=Q;super.setNotificationHandler(X,($)=>{let G=$.params;this.onEventDispatch(K,G),Z.onHandler?.(G);for(let j of[...Z.listeners])j(G)})}return Q}setEventHandler(K,Q){let X=this._ensureEventSlot(K);if(X.onHandler&&Q)console.warn(`[MCP Apps] on${String(K)} handler replaced. Use addEventListener(\"${String(K)}\", …) to add multiple listeners without replacing.`);X.onHandler=Q}getEventHandler(K){return this._eventSlots.get(K)?.onHandler}addEventListener(K,Q){this._ensureEventSlot(K).listeners.push(Q)}removeEventListener(K,Q){let X=this._eventSlots.get(K);if(!X)return;let Y=X.listeners.indexOf(Q);if(Y!==-1)X.listeners.splice(Y,1)}setRequestHandler=(K,Q)=>{this._assertMethodNotRegistered(K,\"setRequestHandler\"),super.setRequestHandler(K,Q)};setNotificationHandler=(K,Q)=>{this._assertMethodNotRegistered(K,\"setNotificationHandler\"),super.setNotificationHandler(K,Q)};warnIfRequestHandlerReplaced(K,Q,X){if(Q&&X)console.warn(`[MCP Apps] ${K} handler replaced. Previous handler will no longer be called.`)}replaceRequestHandler=(K,Q)=>{let X=K.shape.method.value;this._registeredMethods.add(X),super.setRequestHandler(K,Q)};_assertMethodNotRegistered(K,Q){let X=K.shape.method.value;if(this._registeredMethods.has(X))throw Error(`Handler for \"${X}\" already registered (via ${Q}). Use addEventListener() to attach multiple listeners, or the on* setter for replace semantics.`);this._registeredMethods.add(X)}}import{JSONRPCMessageSchema as PJ}from\"@modelcontextprotocol/sdk/types.js\";var w=\"2026-01-26\",QJ=\"ui/open-link\",XJ=\"ui/download-file\",YJ=\"ui/message\",ZJ=\"ui/notifications/sandbox-proxy-ready\",$J=\"ui/notifications/sandbox-resource-ready\",GJ=\"ui/notifications/size-changed\",jJ=\"ui/notifications/tool-input\",H=\"ui/notifications/tool-input-partial\",WJ=\"ui/notifications/tool-result\",LJ=\"ui/notifications/tool-cancelled\",NJ=\"ui/notifications/host-context-changed\",BJ=\"ui/notifications/request-teardown\",VJ=\"ui/resource-teardown\",_J=\"ui/initialize\",OJ=\"ui/notifications/initialized\",qJ=\"ui/request-display-mode\";class B{eventTarget;eventSource;messageListener;constructor(K=window.parent,Q){this.eventTarget=K;this.eventSource=Q;this.messageListener=(X)=>{if(Q&&X.source!==this.eventSource){console.debug(\"Ignoring message from unknown source\",X);return}let Y=PJ.safeParse(X.data);if(Y.success)console.debug(\"Parsed message\",Y.data),this.onmessage?.(Y.data);else if(X.data?.jsonrpc!==\"2.0\")console.debug(\"Ignoring non-JSON-RPC message\",Y.error.message,X);else console.error(\"Failed to parse message\",Y.error.message,X),this.onerror?.(Error(\"Invalid JSON-RPC message received: \"+Y.error.message))}}async start(){window.addEventListener(\"message\",this.messageListener)}async send(K,Q){if(K.method!==H)console.debug(\"Sending message\",K);this.eventTarget.postMessage(K,\"*\")}async close(){window.removeEventListener(\"message\",this.messageListener),this.onclose?.()}onclose;onerror;onmessage;sessionId;setProtocolVersion}import{z as J}from\"zod/v4\";import{ContentBlockSchema as r,CallToolResultSchema as DJ,EmbeddedResourceSchema as FJ,ImplementationSchema as l,RequestIdSchema as EJ,ResourceLinkSchema as IJ,ToolSchema as UJ}from\"@modelcontextprotocol/sdk/types.js\";var i=J.union([J.literal(\"light\"),J.literal(\"dark\")]).describe(\"Color theme preference for the host environment.\"),V=J.union([J.literal(\"inline\"),J.literal(\"fullscreen\"),J.literal(\"pip\")]).describe(\"Display mode for UI presentation.\"),RJ=J.union([J.literal(\"--color-background-primary\"),J.literal(\"--color-background-secondary\"),J.literal(\"--color-background-tertiary\"),J.literal(\"--color-background-inverse\"),J.literal(\"--color-background-ghost\"),J.literal(\"--color-background-info\"),J.literal(\"--color-background-danger\"),J.literal(\"--color-background-success\"),J.literal(\"--color-background-warning\"),J.literal(\"--color-background-disabled\"),J.literal(\"--color-text-primary\"),J.literal(\"--color-text-secondary\"),J.literal(\"--color-text-tertiary\"),J.literal(\"--color-text-inverse\"),J.literal(\"--color-text-ghost\"),J.literal(\"--color-text-info\"),J.literal(\"--color-text-danger\"),J.literal(\"--color-text-success\"),J.literal(\"--color-text-warning\"),J.literal(\"--color-text-disabled\"),J.literal(\"--color-border-primary\"),J.literal(\"--color-border-secondary\"),J.literal(\"--color-border-tertiary\"),J.literal(\"--color-border-inverse\"),J.literal(\"--color-border-ghost\"),J.literal(\"--color-border-info\"),J.literal(\"--color-border-danger\"),J.literal(\"--color-border-success\"),J.literal(\"--color-border-warning\"),J.literal(\"--color-border-disabled\"),J.literal(\"--color-ring-primary\"),J.literal(\"--color-ring-secondary\"),J.literal(\"--color-ring-inverse\"),J.literal(\"--color-ring-info\"),J.literal(\"--color-ring-danger\"),J.literal(\"--color-ring-success\"),J.literal(\"--color-ring-warning\"),J.literal(\"--font-sans\"),J.literal(\"--font-mono\"),J.literal(\"--font-weight-normal\"),J.literal(\"--font-weight-medium\"),J.literal(\"--font-weight-semibold\"),J.literal(\"--font-weight-bold\"),J.literal(\"--font-text-xs-size\"),J.literal(\"--font-text-sm-size\"),J.literal(\"--font-text-md-size\"),J.literal(\"--font-text-lg-size\"),J.literal(\"--font-heading-xs-size\"),J.literal(\"--font-heading-sm-size\"),J.literal(\"--font-heading-md-size\"),J.literal(\"--font-heading-lg-size\"),J.literal(\"--font-heading-xl-size\"),J.literal(\"--font-heading-2xl-size\"),J.literal(\"--font-heading-3xl-size\"),J.literal(\"--font-text-xs-line-height\"),J.literal(\"--font-text-sm-line-height\"),J.literal(\"--font-text-md-line-height\"),J.literal(\"--font-text-lg-line-height\"),J.literal(\"--font-heading-xs-line-height\"),J.literal(\"--font-heading-sm-line-height\"),J.literal(\"--font-heading-md-line-height\"),J.literal(\"--font-heading-lg-line-height\"),J.literal(\"--font-heading-xl-line-height\"),J.literal(\"--font-heading-2xl-line-height\"),J.literal(\"--font-heading-3xl-line-height\"),J.literal(\"--border-radius-xs\"),J.literal(\"--border-radius-sm\"),J.literal(\"--border-radius-md\"),J.literal(\"--border-radius-lg\"),J.literal(\"--border-radius-xl\"),J.literal(\"--border-radius-full\"),J.literal(\"--border-width-regular\"),J.literal(\"--shadow-hairline\"),J.literal(\"--shadow-sm\"),J.literal(\"--shadow-md\"),J.literal(\"--shadow-lg\")]).describe(\"CSS variable keys available to MCP apps for theming.\"),MJ=J.record(RJ.describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`),J.union([J.string(),J.undefined()]).describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`)).describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`),zJ=J.object({method:J.literal(\"ui/open-link\"),params:J.object({url:J.string().describe(\"URL to open in the host's browser\")})}),A=J.object({isError:J.boolean().optional().describe(\"True if the host failed to open the URL (e.g., due to security policy).\")}).passthrough(),k=J.object({isError:J.boolean().optional().describe(\"True if the download failed (e.g., user cancelled or host denied).\")}).passthrough(),C=J.object({isError:J.boolean().optional().describe(\"True if the host rejected or failed to deliver the message.\")}).passthrough(),wJ=J.object({method:J.literal(\"ui/notifications/sandbox-proxy-ready\"),params:J.object({})}),P=J.object({connectDomains:J.array(J.string()).optional().describe(`Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP \\`connect-src\\` directive\n- Empty or omitted → no network connections (secure default)`),resourceDomains:J.array(J.string()).optional().describe(\"Origins for static resources (images, scripts, stylesheets, fonts, media).\\n\\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\\n- Wildcard subdomains supported: `https://*.example.com`\\n- Empty or omitted → no network resources (secure default)\"),frameDomains:J.array(J.string()).optional().describe(\"Origins for nested iframes.\\n\\n- Maps to CSP `frame-src` directive\\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)\"),baseUriDomains:J.array(J.string()).optional().describe(\"Allowed base URIs for the document.\\n\\n- Maps to CSP `base-uri` directive\\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)\")}),D=J.object({camera:J.object({}).optional().describe(\"Request camera access.\\n\\nMaps to Permission Policy `camera` feature.\"),microphone:J.object({}).optional().describe(\"Request microphone access.\\n\\nMaps to Permission Policy `microphone` feature.\"),geolocation:J.object({}).optional().describe(\"Request geolocation access.\\n\\nMaps to Permission Policy `geolocation` feature.\"),clipboardWrite:J.object({}).optional().describe(\"Request clipboard write access.\\n\\nMaps to Permission Policy `clipboard-write` feature.\")}),HJ=J.object({method:J.literal(\"ui/notifications/size-changed\"),params:J.object({width:J.number().optional().describe(\"New width in pixels.\"),height:J.number().optional().describe(\"New height in pixels.\")})}),S=J.object({method:J.literal(\"ui/notifications/tool-input\"),params:J.object({arguments:J.record(J.string(),J.unknown().describe(\"Complete tool call arguments as key-value pairs.\")).optional().describe(\"Complete tool call arguments as key-value pairs.\")})}),b=J.object({method:J.literal(\"ui/notifications/tool-input-partial\"),params:J.object({arguments:J.record(J.string(),J.unknown().describe(\"Partial tool call arguments (incomplete, may change).\")).optional().describe(\"Partial tool call arguments (incomplete, may change).\")})}),x=J.object({method:J.literal(\"ui/notifications/tool-cancelled\"),params:J.object({reason:J.string().optional().describe('Optional reason for the cancellation (e.g., \"user action\", \"timeout\").')})}),p=J.object({fonts:J.string().optional()}),n=J.object({variables:MJ.optional().describe(\"CSS variables for theming the app.\"),css:p.optional().describe(\"CSS blocks that apps can inject.\")}),v=J.object({method:J.literal(\"ui/resource-teardown\"),params:J.object({})}),TJ=J.record(J.string(),J.unknown()),T=J.object({text:J.object({}).optional().describe(\"Host supports text content blocks.\"),image:J.object({}).optional().describe(\"Host supports image content blocks.\"),audio:J.object({}).optional().describe(\"Host supports audio content blocks.\"),resource:J.object({}).optional().describe(\"Host supports resource content blocks.\"),resourceLink:J.object({}).optional().describe(\"Host supports resource link content blocks.\"),structuredContent:J.object({}).optional().describe(\"Host supports structured content.\")}),AJ=J.object({method:J.literal(\"ui/notifications/request-teardown\"),params:J.object({}).optional()}),o=J.object({experimental:J.object({}).optional().describe(\"Experimental features (structure TBD).\"),openLinks:J.object({}).optional().describe(\"Host supports opening external URLs.\"),downloadFile:J.object({}).optional().describe(\"Host supports file downloads via ui/download-file.\"),serverTools:J.object({listChanged:J.boolean().optional().describe(\"Host supports tools/list_changed notifications.\")}).optional().describe(\"Host can proxy tool calls to the MCP server.\"),serverResources:J.object({listChanged:J.boolean().optional().describe(\"Host supports resources/list_changed notifications.\")}).optional().describe(\"Host can proxy resource reads to the MCP server.\"),logging:J.object({}).optional().describe(\"Host accepts log messages.\"),sandbox:J.object({permissions:D.optional().describe(\"Permissions granted by the host (camera, microphone, geolocation).\"),csp:P.optional().describe(\"CSP domains approved by the host.\")}).optional().describe(\"Sandbox configuration applied by the host.\"),updateModelContext:T.optional().describe(\"Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.\"),message:T.optional().describe(\"Host supports receiving content messages (ui/message) from the view.\"),sampling:J.object({tools:J.object({}).optional().describe(\"Host supports tool use via `tools` and `toolChoice` parameters.\")}).optional().describe(\"Host supports LLM sampling (sampling/createMessage) from the view.\\nMirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.\")}),a=J.object({experimental:J.object({}).optional().describe(\"Experimental features (structure TBD).\"),tools:J.object({listChanged:J.boolean().optional().describe(\"App supports tools/list_changed notifications.\")}).optional().describe(\"App exposes MCP-style tools that the host can call.\"),availableDisplayModes:J.array(V).optional().describe(\"Display modes the app supports.\")}),kJ=J.object({method:J.literal(\"ui/notifications/initialized\"),params:J.object({}).optional()}),CJ=J.object({csp:P.optional().describe(\"Content Security Policy configuration for UI resources.\"),permissions:D.optional().describe(\"Sandbox permissions requested by the UI resource.\"),domain:J.string().optional().describe(`Dedicated origin for view sandbox.\n\nUseful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.\n\n**Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:\n- Hash-based subdomains (e.g., \\`{hash}.claudemcpcontent.com\\`)\n- URL-derived subdomains (e.g., \\`www-example-com.oaiusercontent.com\\`)\n\nIf omitted, host uses default sandbox origin (typically per-conversation).`),prefersBorder:J.boolean().optional().describe(`Visual boundary preference - true if view prefers a visible border.\n\nBoolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.\n\n- \\`true\\`: request visible border + background\n- \\`false\\`: request no visible border + background\n- omitted: host decides border`)}),SJ=J.object({method:J.literal(\"ui/request-display-mode\"),params:J.object({mode:V.describe(\"The display mode being requested.\")})}),g=J.object({mode:V.describe(\"The display mode that was actually set. May differ from requested if not supported.\")}).passthrough(),s=J.union([J.literal(\"model\"),J.literal(\"app\")]).describe(\"Tool visibility scope - who can access the tool.\"),bJ=J.object({resourceUri:J.string().optional(),visibility:J.array(s).optional().describe(`Who can access this tool. Default: [\"model\", \"app\"]\n- \"model\": Tool visible to and callable by the agent\n- \"app\": Tool callable by the app from this server only`),csp:J.never().optional(),permissions:J.never().optional()}),_K=J.object({mimeTypes:J.array(J.string()).optional().describe('Array of supported MIME types for UI resources.\\nMust include `\"text/html;profile=mcp-app\"` for MCP Apps support.')}),xJ=J.object({method:J.literal(\"ui/download-file\"),params:J.object({contents:J.array(J.union([FJ,IJ])).describe(\"Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.\")})}),vJ=J.object({method:J.literal(\"ui/message\"),params:J.object({role:J.literal(\"user\").describe('Message role, currently only \"user\" is supported.'),content:J.array(r).describe(\"Message content blocks (text, image, etc.).\")})}),gJ=J.object({method:J.literal(\"ui/notifications/sandbox-resource-ready\"),params:J.object({html:J.string().describe(\"HTML content to load into the inner iframe.\"),sandbox:J.string().optional().describe(\"Optional override for the inner iframe's sandbox attribute.\"),csp:P.optional().describe(\"CSP configuration from resource metadata.\"),permissions:D.optional().describe(\"Sandbox permissions from resource metadata.\")})}),y=J.object({method:J.literal(\"ui/notifications/tool-result\"),params:DJ.describe(\"Standard MCP tool execution result.\")}),f=J.object({toolInfo:J.object({id:EJ.optional().describe(\"JSON-RPC id of the tools/call request.\"),tool:UJ.describe(\"Tool definition including name, inputSchema, etc.\")}).optional().describe(\"Metadata of the tool call that instantiated this App.\"),theme:i.optional().describe(\"Current color theme preference.\"),styles:n.optional().describe(\"Style configuration for theming the app.\"),displayMode:V.optional().describe(\"How the UI is currently displayed.\"),availableDisplayModes:J.array(V).optional().describe(\"Display modes the host supports.\"),containerDimensions:J.union([J.object({height:J.number().describe(\"Fixed container height in pixels.\")}),J.object({maxHeight:J.union([J.number(),J.undefined()]).optional().describe(\"Maximum container height in pixels.\")})]).and(J.union([J.object({width:J.number().describe(\"Fixed container width in pixels.\")}),J.object({maxWidth:J.union([J.number(),J.undefined()]).optional().describe(\"Maximum container width in pixels.\")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other\ncontainer holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:J.string().optional().describe(\"User's language and region preference in BCP 47 format.\"),timeZone:J.string().optional().describe(\"User's timezone in IANA format.\"),userAgent:J.string().optional().describe(\"Host application identifier.\"),platform:J.union([J.literal(\"web\"),J.literal(\"desktop\"),J.literal(\"mobile\")]).optional().describe(\"Platform type for responsive design decisions.\"),deviceCapabilities:J.object({touch:J.boolean().optional().describe(\"Whether the device supports touch input.\"),hover:J.boolean().optional().describe(\"Whether the device supports hover interactions.\")}).optional().describe(\"Device input capabilities.\"),safeAreaInsets:J.object({top:J.number().describe(\"Top safe area inset in pixels.\"),right:J.number().describe(\"Right safe area inset in pixels.\"),bottom:J.number().describe(\"Bottom safe area inset in pixels.\"),left:J.number().describe(\"Left safe area inset in pixels.\")}).optional().describe(\"Mobile safe area boundaries in pixels.\")}).passthrough(),d=J.object({method:J.literal(\"ui/notifications/host-context-changed\"),params:f.describe(\"Partial context update containing only changed fields.\")}),yJ=J.object({method:J.literal(\"ui/update-model-context\"),params:J.object({content:J.array(r).optional().describe(\"Context content blocks (text, image, etc.).\"),structuredContent:J.record(J.string(),J.unknown().describe(\"Structured content for machine-readable context data.\")).optional().describe(\"Structured content for machine-readable context data.\")})}),fJ=J.object({method:J.literal(\"ui/initialize\"),params:J.object({appInfo:l.describe(\"App identification (name and version).\"),appCapabilities:a.describe(\"Features and capabilities this app provides.\"),protocolVersion:J.string().describe(\"Protocol version this app supports.\")})}),u=J.object({protocolVersion:J.string().describe('Negotiated protocol version string (e.g., \"2025-11-21\").'),hostInfo:l.describe(\"Host application identification and version.\"),hostCapabilities:o.describe(\"Features and capabilities provided by the host.\"),hostContext:f.describe(\"Rich context about the host environment.\")}).passthrough();var dJ={target:\"draft-2020-12\"};async function h(K,Q){let X=K[\"~standard\"];if(X.jsonSchema)return X.jsonSchema[Q](dJ);if(X.vendor===\"zod\"){let{z:Y}=await import(\"zod/v4\");return Y.toJSONSchema(K,{io:Q})}throw Error(`Schema (vendor: ${X.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function m(K,Q,X=\"\"){let Y=await K[\"~standard\"].validate(Q);if(Y.issues){let Z=Y.issues.map(($)=>{let G=$.path?.map((j)=>typeof j===\"object\"?j.key:j).join(\".\");return G?`${G}: ${$.message}`:$.message}).join(\"; \");throw Error(X+Z)}return Y.value}import{z as aJ}from\"zod/v4\";function F(){let K=document.documentElement.getAttribute(\"data-theme\");if(K===\"dark\"||K===\"light\")return K;return document.documentElement.classList.contains(\"dark\")?\"dark\":\"light\"}function E(K){let Q=document.documentElement;Q.setAttribute(\"data-theme\",K),Q.style.colorScheme=K}function I(K,Q=document.documentElement){for(let[X,Y]of Object.entries(K))if(Y!==void 0)Q.style.setProperty(X,Y)}function U(K){if(document.getElementById(\"__mcp-host-fonts\"))return;let X=document.createElement(\"style\");X.id=\"__mcp-host-fonts\",X.textContent=K,document.head.appendChild(X)}var NQ=\"ui/resourceUri\",BQ=\"text/html;profile=mcp-app\";class R extends z{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;_registeredTools={};_initializedSent=!1;_assertInitialized(K){if(this._initializedSent)return;let Q=`[ext-apps] App.${K}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if(this.options?.strict)throw Error(Q);console.warn(`${Q}. This will throw in a future release.`)}eventSchemas={toolinput:S,toolinputpartial:b,toolresult:y,toolcancelled:x,hostcontextchanged:d};static ONE_SHOT_EVENTS=new Set([\"toolinput\",\"toolinputpartial\",\"toolresult\",\"toolcancelled\"]);_everHadListener=new Set;_assertHandlerTiming(K){if(!R.ONE_SHOT_EVENTS.has(K)||this._everHadListener.has(K))return;if(this._everHadListener.add(K),!this._initializedSent)return;let Q=`[ext-apps] \"${String(K)}\" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if(this.options?.strict)throw Error(Q);console.warn(Q)}setEventHandler(K,Q){if(Q)this._assertHandlerTiming(K);super.setEventHandler(K,Q)}addEventListener(K,Q){this._assertHandlerTiming(K),super.addEventListener(K,Q)}onEventDispatch(K,Q){if(K===\"hostcontextchanged\")this._hostContext={...this._hostContext,...Q}}constructor(K,Q={},X={autoResize:!0}){super(X);this._appInfo=K;this._capabilities=Q;this.options=X;if(!X.allowUnsafeEval)aJ.config({jitless:!0});this.setRequestHandler(nJ,(Y)=>{return console.log(\"Received ping:\",Y.params),{}}),this.setEventHandler(\"hostcontextchanged\",void 0)}registerCapabilities(K){if(this.transport)throw Error(\"Cannot register capabilities after transport is established\");this._capabilities=uJ(this._capabilities,K)}registerTool(K,Q,X){if(this._registeredTools[K])throw Error(`Tool ${K} is already registered`);let Y=this,Z=()=>{if(Y._initializedSent&&Y._capabilities.tools?.listChanged)Y.sendToolListChanged()},$=Q.inputSchema!==void 0,G={title:Q.title,description:Q.description,inputSchema:Q.inputSchema,outputSchema:Q.outputSchema,annotations:Q.annotations,_meta:Q._meta,enabled:!0,enable(){this.enabled=!0,Z()},disable(){this.enabled=!1,Z()},update(j){Object.assign(this,j),Z()},remove(){if(Y._registeredTools[K]!==G)return;delete Y._registeredTools[K],Z()},handler:async(j,W)=>{if(!G.enabled)throw Error(`Tool ${K} is disabled`);let L;if($){let _=G.inputSchema,O=_?await m(_,j??{},`Invalid input for tool ${K}: `):j??{};L=await X(O,W)}else L=await X(W);if(G.outputSchema&&!L.isError)L.structuredContent=await m(G.outputSchema,L.structuredContent,`Invalid output for tool ${K}: `);return L}};if(this._registeredTools[K]=G,!this._capabilities.tools&&!this.transport)this.registerCapabilities({tools:{listChanged:!0}});return this.ensureToolHandlersInitialized(),Z(),G}_toolHandlersInitialized=!1;ensureToolHandlersInitialized(){if(this._toolHandlersInitialized)return;this._toolHandlersInitialized=!0,this.oncalltool=async(K,Q)=>{let X=this._registeredTools[K.name];if(!X)throw Error(`Tool ${K.name} not found`);return X.handler(K.arguments,Q)},this.onlisttools=async(K,Q)=>{return{tools:await Promise.all(Object.entries(this._registeredTools).filter(([Y,Z])=>Z.enabled).map(async([Y,Z])=>{let $={name:Y,title:Z.title,description:Z.description,inputSchema:Z.inputSchema?await h(Z.inputSchema,\"input\"):{type:\"object\",properties:{}}};if(Z.outputSchema)$.outputSchema=await h(Z.outputSchema,\"output\");if(Z.annotations)$.annotations=Z.annotations;if(Z._meta)$._meta=Z._meta;return $}))}}}async sendToolListChanged(K={}){this._assertInitialized(\"sendToolListChanged\"),await this.notification({method:\"notifications/tools/list_changed\",params:K})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler(\"toolinput\")}set ontoolinput(K){this.setEventHandler(\"toolinput\",K)}get ontoolinputpartial(){return this.getEventHandler(\"toolinputpartial\")}set ontoolinputpartial(K){this.setEventHandler(\"toolinputpartial\",K)}get ontoolresult(){return this.getEventHandler(\"toolresult\")}set ontoolresult(K){this.setEventHandler(\"toolresult\",K)}get ontoolcancelled(){return this.getEventHandler(\"toolcancelled\")}set ontoolcancelled(K){this.setEventHandler(\"toolcancelled\",K)}get onhostcontextchanged(){return this.getEventHandler(\"hostcontextchanged\")}set onhostcontextchanged(K){this.setEventHandler(\"hostcontextchanged\",K)}_onteardown;get onteardown(){return this._onteardown}set onteardown(K){this.warnIfRequestHandlerReplaced(\"onteardown\",this._onteardown,K),this._onteardown=K,this.replaceRequestHandler(v,(Q,X)=>{if(!this._onteardown)throw Error(\"No onteardown handler set\");return this._onteardown(Q.params,X)})}_oncalltool;get oncalltool(){return this._oncalltool}set oncalltool(K){this.warnIfRequestHandlerReplaced(\"oncalltool\",this._oncalltool,K),this._oncalltool=K,this.replaceRequestHandler(hJ,(Q,X)=>{if(!this._oncalltool)throw Error(\"No oncalltool handler set\");return this._oncalltool(Q.params,X)})}_onlisttools;get onlisttools(){return this._onlisttools}set onlisttools(K){this.warnIfRequestHandlerReplaced(\"onlisttools\",this._onlisttools,K),this._onlisttools=K,this.replaceRequestHandler(pJ,(Q,X)=>{if(!this._onlisttools)throw Error(\"No onlisttools handler set\");return this._onlisttools(Q.params,X)})}assertCapabilityForMethod(K){switch(K){case\"sampling/createMessage\":if(!this._hostCapabilities?.sampling)throw Error(`Host does not support sampling (required for ${K})`);break}}assertRequestHandlerCapability(K){switch(K){case\"tools/call\":case\"tools/list\":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${K})`);return;case\"ping\":case\"ui/resource-teardown\":return;default:throw Error(`No handler for method ${K} registered`)}}assertNotificationCapability(K){}assertTaskCapability(K){throw Error(\"Tasks are not supported in MCP Apps\")}assertTaskHandlerCapability(K){throw Error(\"Task handlers are not supported in MCP Apps\")}async callServerTool(K,Q){if(this._assertInitialized(\"callServerTool\"),typeof K===\"string\")throw Error(`callServerTool() expects an object as its first argument, but received a string (\"${K}\"). Did you mean: callServerTool({ name: \"${K}\", arguments: { ... } })?`);return await this.request({method:\"tools/call\",params:K},mJ,{onprogress:()=>{},resetTimeoutOnProgress:!0,...Q})}async readServerResource(K,Q){return this._assertInitialized(\"readServerResource\"),await this.request({method:\"resources/read\",params:K},oJ,Q)}async listServerResources(K,Q){return this._assertInitialized(\"listServerResources\"),await this.request({method:\"resources/list\",params:K},iJ,Q)}async createSamplingMessage(K,Q){this._assertInitialized(\"createSamplingMessage\");let X=K.tools?rJ:cJ;return await this.request({method:\"sampling/createMessage\",params:K},X,Q)}sendMessage(K,Q){return this._assertInitialized(\"sendMessage\"),this.request({method:\"ui/message\",params:K},C,Q)}sendLog(K){return this.notification({method:\"notifications/message\",params:K})}updateModelContext(K,Q){return this._assertInitialized(\"updateModelContext\"),this.request({method:\"ui/update-model-context\",params:K},lJ,Q)}openLink(K,Q){return this._assertInitialized(\"openLink\"),this.request({method:\"ui/open-link\",params:K},A,Q)}sendOpenLink=this.openLink;downloadFile(K,Q){return this._assertInitialized(\"downloadFile\"),this.request({method:\"ui/download-file\",params:K},k,Q)}requestTeardown(K={}){return this.notification({method:\"ui/notifications/request-teardown\",params:K})}requestDisplayMode(K,Q){return this._assertInitialized(\"requestDisplayMode\"),this.request({method:\"ui/request-display-mode\",params:K},g,Q)}sendSizeChanged(K){return this.notification({method:\"ui/notifications/size-changed\",params:K})}setupSizeChangedNotifications(){let K=!1,Q=0,X=0,Y=()=>{if(K)return;K=!0,requestAnimationFrame(()=>{K=!1;let $=document.documentElement,G=$.style.height;$.style.height=\"max-content\";let j=Math.ceil($.getBoundingClientRect().height);$.style.height=G;let W=Math.ceil(window.innerWidth);if(W!==Q||j!==X)Q=W,X=j,this.sendSizeChanged({width:W,height:j})})};Y();let Z=new ResizeObserver(Y);return Z.observe(document.documentElement),Z.observe(document.body),()=>Z.disconnect()}async connect(K=new B(window.parent,window.parent),Q){if(this.transport)throw Error(\"App is already connected. Call close() before connecting again.\");this._initializedSent=!1,await super.connect(K);try{let X=await this.request({method:\"ui/initialize\",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:w}},u,Q);if(X===void 0)throw Error(`Server sent invalid initialize result: ${X}`);if(this._hostCapabilities=X.hostCapabilities,this._hostInfo=X.hostInfo,this._hostContext=X.hostContext,await this.notification({method:\"ui/notifications/initialized\"}),this._initializedSent=!0,this.options?.autoResize)this.setupSizeChangedNotifications()}catch(X){throw this.close(),X}}}function IQ({appInfo:K,capabilities:Q,onAppCreated:X,autoResize:Y=!0,strict:Z}){let[$,G]=c(null),[j,W]=c(!1),[L,_]=c(null);return sJ(()=>{let O=!0,N;async function e(){try{let q=new B(window.parent,window.parent);if(N=new R(K,Q,{autoResize:Y,strict:Z}),X?.(N),await N.connect(q),!O){N.close();return}G(N),W(!0),_(null)}catch(q){if(O)G(null),W(!1),_(q instanceof Error?q:Error(\"Failed to connect\"))}}return e(),()=>{O=!1,N?.close()}},[]),{app:$,isConnected:j,error:L}}import{useEffect as tJ}from\"react\";function wQ(K,Q){tJ(()=>{if(!K)return;return K.setupSizeChangedNotifications()},[K,Q])}import{useEffect as eJ,useState as JK}from\"react\";function kQ(){let[K,Q]=JK(F);return eJ(()=>{let X=new MutationObserver(()=>{Q(F())});return X.observe(document.documentElement,{attributes:!0,attributeFilter:[\"data-theme\",\"class\"],characterData:!1,childList:!1,subtree:!1}),()=>X.disconnect()},[]),K}import{useEffect as M,useRef as t}from\"react\";function KK(K,Q){let X=t(!1);M(()=>{if(X.current)return;if(Q?.theme)E(Q.theme);if(Q?.styles?.variables)I(Q.styles.variables);if(Q?.theme||Q?.styles?.variables)X.current=!0},[Q]),M(()=>{if(!K)return;let Y=(Z)=>{if(Z.theme)E(Z.theme);if(Z.styles?.variables)I(Z.styles.variables)};return K.addEventListener(\"hostcontextchanged\",Y),()=>K.removeEventListener(\"hostcontextchanged\",Y)},[K])}function QK(K,Q){let X=t(!1);M(()=>{if(X.current)return;if(Q?.styles?.css?.fonts)U(Q.styles.css.fonts),X.current=!0},[Q]),M(()=>{if(!K)return;let Y=(Z)=>{if(Z.styles?.css?.fonts)U(Z.styles.css.fonts)};return K.addEventListener(\"hostcontextchanged\",Y),()=>K.removeEventListener(\"hostcontextchanged\",Y)},[K])}function xQ(K,Q){KK(K,Q),QK(K,Q)}export{xQ as useHostStyles,KK as useHostStyleVariables,QK as useHostFonts,kQ as useDocumentTheme,wQ as useAutoResize,IQ as useApp,F as getDocumentTheme,I as applyHostStyleVariables,U as applyHostFonts,E as applyDocumentTheme,WJ as TOOL_RESULT_METHOD,H as TOOL_INPUT_PARTIAL_METHOD,jJ as TOOL_INPUT_METHOD,LJ as TOOL_CANCELLED_METHOD,GJ as SIZE_CHANGED_METHOD,$J as SANDBOX_RESOURCE_READY_METHOD,ZJ as SANDBOX_PROXY_READY_METHOD,NQ as RESOURCE_URI_META_KEY,VJ as RESOURCE_TEARDOWN_METHOD,BQ as RESOURCE_MIME_TYPE,BJ as REQUEST_TEARDOWN_METHOD,qJ as REQUEST_DISPLAY_MODE_METHOD,z as ProtocolWithEvents,B as PostMessageTransport,QJ as OPEN_LINK_METHOD,yJ as McpUiUpdateModelContextRequestSchema,s as McpUiToolVisibilitySchema,y as McpUiToolResultNotificationSchema,bJ as McpUiToolMetaSchema,b as McpUiToolInputPartialNotificationSchema,S as McpUiToolInputNotificationSchema,x as McpUiToolCancelledNotificationSchema,i as McpUiThemeSchema,T as McpUiSupportedContentBlockModalitiesSchema,HJ as McpUiSizeChangedNotificationSchema,gJ as McpUiSandboxResourceReadyNotificationSchema,wJ as McpUiSandboxProxyReadyNotificationSchema,TJ as McpUiResourceTeardownResultSchema,v as McpUiResourceTeardownRequestSchema,D as McpUiResourcePermissionsSchema,CJ as McpUiResourceMetaSchema,P as McpUiResourceCspSchema,AJ as McpUiRequestTeardownNotificationSchema,g as McpUiRequestDisplayModeResultSchema,SJ as McpUiRequestDisplayModeRequestSchema,A as McpUiOpenLinkResultSchema,zJ as McpUiOpenLinkRequestSchema,C as McpUiMessageResultSchema,vJ as McpUiMessageRequestSchema,kJ as McpUiInitializedNotificationSchema,u as McpUiInitializeResultSchema,fJ as McpUiInitializeRequestSchema,n as McpUiHostStylesSchema,p as McpUiHostCssSchema,f as McpUiHostContextSchema,d as McpUiHostContextChangedNotificationSchema,o as McpUiHostCapabilitiesSchema,k as McpUiDownloadFileResultSchema,xJ as McpUiDownloadFileRequestSchema,V as McpUiDisplayModeSchema,a as McpUiAppCapabilitiesSchema,YJ as MESSAGE_METHOD,w as LATEST_PROTOCOL_VERSION,_J as INITIALIZE_METHOD,OJ as INITIALIZED_METHOD,NJ as HOST_CONTEXT_CHANGED_METHOD,XJ as DOWNLOAD_FILE_METHOD,R as App};\n","import { useCallback, useSyncExternalStore } from 'react';\nimport type { App, McpUiHostContext, McpUiStyles } from '@modelcontextprotocol/ext-apps';\nimport {\n applyDocumentTheme,\n applyHostStyleVariables,\n applyHostFonts,\n} from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\nimport { DEFAULT_STYLE_VARIABLES } from '../lib/default-style-variables';\n\n/**\n * Per-app subscriber registry.\n * The App class only supports a single onhostcontextchanged callback,\n * so we multiplex it to allow multiple hook instances to subscribe.\n *\n * Also applies `data-theme` and `color-scheme` to the document element\n * so that CSS selectors like `[data-theme=\"dark\"]` and Tailwind's `dark:`\n * variant work automatically.\n */\nconst registries = new WeakMap<App, Set<() => void>>();\n\n/**\n * Apply style variables to the document, falling back to defaults.\n * Host-provided variables override defaults since they're applied after.\n */\nfunction applyStyles(variables: McpUiStyles | undefined) {\n // Always apply defaults first so all CSS variables are defined\n applyHostStyleVariables(DEFAULT_STYLE_VARIABLES);\n // Override with host-provided values (if any)\n if (variables) {\n applyHostStyleVariables(variables);\n }\n}\n\nfunction getRegistry(app: App): Set<() => void> {\n let subs = registries.get(app);\n if (!subs) {\n subs = new Set();\n registries.set(app, subs);\n\n // Apply initial theme and style variables from the host context received during initialization\n const ctx = app.getHostContext();\n if (ctx?.theme) {\n applyDocumentTheme(ctx.theme);\n }\n applyStyles(ctx?.styles?.variables);\n if (ctx?.styles?.css?.fonts) {\n applyHostFonts(ctx.styles.css.fonts);\n }\n\n // Debounce timer for subscriber notifications.\n // Some hosts (e.g. ChatGPT) fire hostcontextchanged at hundreds of Hz while\n // the LLM is generating text, oscillating containerDimensions between two\n // values. Debouncing coalesces these rapid bursts into a single re-render\n // so SafeArea and other dimension-sensitive components don't flicker.\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n app.onhostcontextchanged = () => {\n // Read the full context from the app rather than relying on the\n // callback params, which may be a delta missing unchanged fields\n // like styles when only the theme toggled.\n const ctx = app.getHostContext();\n if (ctx?.theme) {\n applyDocumentTheme(ctx.theme);\n }\n applyStyles(ctx?.styles?.variables);\n if (ctx?.styles?.css?.fonts) {\n applyHostFonts(ctx.styles.css.fonts);\n }\n // Notify subscribers after a brief settling period.\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n for (const fn of subs!) fn();\n }, 50);\n };\n }\n return subs;\n}\n\n/**\n * Reactive access to the MCP Apps host context.\n * Subscribes to host context changes and re-renders when the context updates.\n *\n * @returns The current host context, or null if not connected.\n */\nexport function useHostContext(): McpUiHostContext | null {\n const app = useApp();\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (!app) return () => {};\n const subs = getRegistry(app);\n subs.add(onChange);\n return () => {\n subs.delete(onChange);\n };\n },\n [app]\n );\n\n const getSnapshot = useCallback(() => {\n return app?.getHostContext() ?? null;\n }, [app]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\nexport interface ToolData<TInput = unknown, TOutput = unknown> {\n input: TInput | null;\n inputPartial: TInput | null;\n output: TOutput | null;\n isError: boolean;\n isLoading: boolean;\n isCancelled: boolean;\n cancelReason: string | null;\n}\n\ninterface ToolDataStore<TInput, TOutput> {\n data: ToolData<TInput, TOutput>;\n listeners: Set<() => void>;\n}\n\nconst stores = new WeakMap<App, ToolDataStore<unknown, unknown>>();\n\nfunction getStore<TInput, TOutput>(\n app: App,\n defaultInput?: TInput,\n defaultOutput?: TOutput\n): ToolDataStore<TInput, TOutput> {\n let store = stores.get(app) as ToolDataStore<TInput, TOutput> | undefined;\n if (!store) {\n store = {\n data: {\n input: defaultInput ?? null,\n inputPartial: null,\n output: defaultOutput ?? null,\n isError: false,\n isLoading: !defaultOutput,\n isCancelled: false,\n cancelReason: null,\n },\n listeners: new Set(),\n };\n stores.set(app, store as ToolDataStore<unknown, unknown>);\n\n const notify = () => {\n for (const fn of store!.listeners) fn();\n };\n\n app.ontoolinput = (_params) => {\n store!.data = {\n ...store!.data,\n input: _params.arguments as TInput,\n inputPartial: null,\n };\n notify();\n };\n\n app.ontoolinputpartial = (_params) => {\n store!.data = {\n ...store!.data,\n inputPartial: _params.arguments as TInput,\n };\n notify();\n };\n\n app.ontoolresult = (_params) => {\n store!.data = {\n ...store!.data,\n output: (_params.structuredContent ?? _params.content) as TOutput,\n isError: _params.isError ?? false,\n isLoading: false,\n };\n notify();\n };\n\n app.ontoolcancelled = (_params) => {\n store!.data = {\n ...store!.data,\n isCancelled: true,\n cancelReason: _params.reason ?? null,\n isLoading: false,\n };\n notify();\n };\n }\n return store;\n}\n\n/**\n * Reactive access to tool input and output data from the MCP Apps host.\n *\n * @param defaultInput - Optional default input value before host sends data.\n * @param defaultOutput - Optional default output value before host sends data.\n */\nexport function useToolData<TInput = unknown, TOutput = unknown>(\n defaultInput?: TInput,\n defaultOutput?: TOutput\n): ToolData<TInput, TOutput> {\n const app = useApp();\n const defaultInputRef = useRef(defaultInput);\n const defaultOutputRef = useRef(defaultOutput);\n\n // Cache the null-app snapshot so getSnapshot returns a stable reference.\n // useSyncExternalStore compares with Object.is — a new object each call\n // would cause an infinite re-render loop.\n const nullSnapshot = useMemo<ToolData<TInput, TOutput>>(\n () => ({\n input: defaultInput ?? null,\n inputPartial: null,\n output: defaultOutput ?? null,\n isError: false,\n isLoading: !defaultOutput,\n isCancelled: false,\n cancelReason: null,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [] // Intentionally empty - only compute once on first render\n );\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (!app) return () => {};\n const store = getStore<TInput, TOutput>(\n app,\n defaultInputRef.current,\n defaultOutputRef.current\n );\n store.listeners.add(onChange);\n return () => {\n store.listeners.delete(onChange);\n };\n },\n [app]\n );\n\n const getSnapshot = useCallback((): ToolData<TInput, TOutput> => {\n if (!app) {\n return nullSnapshot;\n }\n return getStore<TInput, TOutput>(app, defaultInputRef.current, defaultOutputRef.current).data;\n }, [app, nullSnapshot]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type DeviceCapabilities = NonNullable<McpUiHostContext['deviceCapabilities']>;\n\nexport function useDeviceCapabilities(): DeviceCapabilities {\n const context = useHostContext();\n return context?.deviceCapabilities ?? {};\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiDisplayMode } from '@modelcontextprotocol/ext-apps';\n\nexport function useDisplayMode(): McpUiDisplayMode {\n const context = useHostContext();\n return context?.displayMode ?? 'inline';\n}\n","import { useHostContext } from './use-host-context';\n\nexport function useLocale(): string {\n const context = useHostContext();\n return context?.locale ?? 'en-US';\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type HostPlatform = NonNullable<McpUiHostContext['platform']>;\n\nexport function usePlatform(): HostPlatform | undefined {\n const context = useHostContext();\n return context?.platform;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\ntype SafeAreaInsets = NonNullable<McpUiHostContext['safeAreaInsets']>;\n\nconst DEFAULT_INSETS: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 };\n\nexport function useSafeArea(): SafeAreaInsets {\n const context = useHostContext();\n return context?.safeAreaInsets ?? DEFAULT_INSETS;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostStyles } from '@modelcontextprotocol/ext-apps';\n\nexport function useStyles(): McpUiHostStyles | undefined {\n const context = useHostContext();\n return context?.styles;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiTheme } from '@modelcontextprotocol/ext-apps';\n\nexport function useTheme(): McpUiTheme {\n const context = useHostContext();\n return context?.theme ?? 'light';\n}\n","import { useHostContext } from './use-host-context';\n\nconst LOCAL_TIME_ZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\nexport function useTimeZone(): string {\n const context = useHostContext();\n return context?.timeZone ?? LOCAL_TIME_ZONE;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type ToolInfo = NonNullable<McpUiHostContext['toolInfo']>;\n\nexport function useToolInfo(): ToolInfo | undefined {\n const context = useHostContext();\n return context?.toolInfo;\n}\n","import { useHostContext } from './use-host-context';\n\nexport function useUserAgent(): string | undefined {\n const context = useHostContext();\n return context?.userAgent;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\ntype ContainerDimensions = NonNullable<McpUiHostContext['containerDimensions']>;\n\nexport type Viewport = ContainerDimensions & {\n maxHeight?: number;\n maxWidth?: number;\n height?: number;\n width?: number;\n};\n\nexport function useViewport(): Viewport | null {\n const context = useHostContext();\n return (context?.containerDimensions as Viewport | undefined) ?? null;\n}\n","import * as React from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n mql.addEventListener('change', onChange);\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n return !!isMobile;\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { useDisplayMode } from './use-display-mode';\nimport { useSafeArea } from './use-safe-area';\nimport { useViewport } from './use-viewport';\n\nexport interface SafeAreaProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n}\n\n/**\n * Wrapper component that applies safe-area padding and viewport constraints.\n *\n * Replaces the common boilerplate of calling `useSafeArea()` + `useViewport()`\n * and manually applying padding/maxHeight/maxWidth styles on a container div.\n *\n * In fullscreen mode, SafeArea fills the iframe viewport (`100dvh`) so that\n * flex column layouts (e.g. sticky header / scrollable content / sticky footer)\n * work correctly without each resource having to handle display mode sizing.\n *\n * @example\n * ```tsx\n * import { SafeArea } from 'sunpeak';\n *\n * export function MyResource() {\n * return (\n * <SafeArea className=\"h-full\">\n * <MyContent />\n * </SafeArea>\n * );\n * }\n * ```\n */\nexport const SafeArea = forwardRef<HTMLDivElement, SafeAreaProps>(function SafeArea(\n { children, style, ...props },\n ref\n) {\n const safeArea = useSafeArea();\n const viewport = useViewport();\n const displayMode = useDisplayMode();\n\n // In fullscreen, fill the iframe viewport so flex layouts work.\n // In inline/pip, do NOT apply containerDimensions.height as an explicit height.\n // Doing so creates a feedback loop: the host sends a small initial placeholder height,\n // SafeArea pins to it, the app fires sizechange with that small height, and the host\n // never corrects it. Instead, let content size naturally so sizechange reports the\n // real rendered height.\n const isFullscreen = displayMode === 'fullscreen';\n // Always use 100dvh in fullscreen — viewport.height may report content height\n // rather than the iframe viewport height, which would defeat overflow scrolling.\n const height = isFullscreen ? '100dvh' : undefined;\n\n return (\n <div\n ref={ref}\n style={{\n // Only set inline padding when safe-area insets are non-zero,\n // so CSS class padding (e.g. Tailwind `p-4`) can serve as defaults.\n paddingTop: safeArea.top || undefined,\n paddingBottom: safeArea.bottom || undefined,\n paddingLeft: safeArea.left || undefined,\n paddingRight: safeArea.right || undefined,\n height,\n // overflow:hidden ensures content doesn't escape the maxHeight boundary,\n // which also lets apps fill the space with their own scrollable container.\n maxHeight: viewport?.maxHeight,\n overflow: viewport?.maxHeight != null ? 'hidden' : undefined,\n width: viewport?.width,\n maxWidth: viewport?.maxWidth,\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n});\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for calling a server tool.\n */\nexport interface CallServerToolParams {\n /** Name of the tool to call */\n name: string;\n /** Arguments to pass to the tool */\n arguments?: Record<string, unknown>;\n}\n\n/**\n * Result from a server tool call.\n */\nexport interface CallServerToolResult {\n /** Content array from the tool response */\n content?: Array<{ type: string; text?: string; [key: string]: unknown }>;\n /** Structured data from the tool response */\n structuredContent?: Record<string, unknown>;\n /** Whether the tool call resulted in an error */\n isError?: boolean;\n}\n\n/**\n * Hook to call other MCP server tools from within an app.\n *\n * Returns a function that invokes a tool on the MCP server and returns its result.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const callServerTool = useCallServerTool();\n *\n * const handleRefresh = async () => {\n * const result = await callServerTool({\n * name: 'get_weather',\n * arguments: { city: 'Tokyo' }\n * });\n * console.log('Weather:', result?.content);\n * };\n *\n * return <button onClick={handleRefresh}>Refresh Weather</button>;\n * }\n * ```\n */\nexport function useCallServerTool(): (\n params: CallServerToolParams\n) => Promise<CallServerToolResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: CallServerToolParams) => {\n if (!app) {\n console.warn('[useCallServerTool] App not connected');\n return undefined;\n }\n return app.callServerTool(params as Parameters<App['callServerTool']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type {\n CreateMessageRequest,\n CreateMessageResult,\n CreateMessageResultWithTools,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport type CreateSamplingMessageParams = CreateMessageRequest['params'];\nexport type { CreateMessageResult, CreateMessageResultWithTools };\n\nexport function useCreateSamplingMessage(): (\n params: CreateSamplingMessageParams\n) => Promise<CreateMessageResult | CreateMessageResultWithTools | undefined> {\n const app = useApp();\n return useCallback(\n async (params: CreateSamplingMessageParams) => {\n if (!app) {\n console.warn('[useCreateSamplingMessage] App not connected');\n return undefined;\n }\n return app.createSamplingMessage(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { McpUiDownloadFileRequest } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for downloading a file through the host.\n */\nexport type DownloadFileParams = McpUiDownloadFileRequest['params'];\n\n/**\n * Result from a file download request.\n */\nexport interface DownloadFileResult {\n /** Whether the download failed (e.g. user cancelled or host denied). */\n isError?: boolean;\n}\n\n/**\n * Hook to download files through the host.\n *\n * Since MCP Apps run in sandboxed iframes where direct downloads are blocked,\n * this provides a host-mediated mechanism for file exports. Supports embedded\n * text/binary content and resource links.\n *\n * @example\n * ```tsx\n * function ExportButton({ data }: { data: unknown }) {\n * const downloadFile = useDownloadFile();\n *\n * const handleExport = async () => {\n * await downloadFile({\n * contents: [{\n * type: 'resource',\n * resource: {\n * uri: 'file:///export.json',\n * mimeType: 'application/json',\n * text: JSON.stringify(data, null, 2),\n * },\n * }],\n * });\n * };\n *\n * return <button onClick={handleExport}>Export JSON</button>;\n * }\n * ```\n */\nexport function useDownloadFile(): (\n params: DownloadFileParams\n) => Promise<DownloadFileResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: DownloadFileParams) => {\n if (!app) {\n console.warn('[useDownloadFile] App not connected');\n return undefined;\n }\n return app.downloadFile(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for listing server resources.\n */\nexport interface ListServerResourcesParams {\n /** Pagination cursor from a previous response. */\n cursor?: string;\n}\n\n/**\n * A resource available on the MCP server.\n */\nexport interface ServerResource {\n /** Resource URI. */\n uri: string;\n /** Human-readable name. */\n name: string;\n /** Optional description. */\n description?: string;\n /** MIME type hint. */\n mimeType?: string;\n}\n\n/**\n * Result from listing server resources.\n */\nexport interface ListServerResourcesResult {\n /** Available resources. */\n resources: ServerResource[];\n /** Cursor for fetching the next page, if more results exist. */\n nextCursor?: string;\n}\n\n/**\n * Hook to discover available resources on the originating MCP server.\n *\n * Resources are proxied through the host. Supports pagination via cursor.\n * Use {@link useReadServerResource} to read a discovered resource.\n *\n * @example\n * ```tsx\n * function ResourcePicker() {\n * const listServerResources = useListServerResources();\n * const [resources, setResources] = useState<ServerResource[]>([]);\n *\n * useEffect(() => {\n * listServerResources().then(result => {\n * if (result) setResources(result.resources);\n * });\n * }, [listServerResources]);\n *\n * return (\n * <ul>\n * {resources.map(r => <li key={r.uri}>{r.name}</li>)}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useListServerResources(): (\n params?: ListServerResourcesParams\n) => Promise<ListServerResourcesResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params?: ListServerResourcesParams) => {\n if (!app) {\n console.warn('[useListServerResources] App not connected');\n return undefined;\n }\n return app.listServerResources(params as Parameters<App['listServerResources']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for opening a link.\n */\nexport interface OpenLinkParams {\n /** URL to open */\n url: string;\n}\n\n/**\n * Hook to open external links through the host.\n *\n * Opens a URL in a new tab/window through the host's link handling mechanism.\n * This is preferred over `window.open()` as it respects the host's security policies.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const openLink = useOpenLink();\n *\n * return (\n * <button onClick={() => openLink({ url: 'https://example.com' })}>\n * Visit Website\n * </button>\n * );\n * }\n * ```\n */\nexport function useOpenLink(): (params: OpenLinkParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: OpenLinkParams) => {\n if (!app) {\n console.warn('[useOpenLink] App not connected');\n return;\n }\n await app.openLink(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for reading a server resource.\n */\nexport interface ReadServerResourceParams {\n /** URI of the resource to read (e.g. `file:///path` or custom scheme). */\n uri: string;\n}\n\n/**\n * Result from reading a server resource.\n */\nexport interface ReadServerResourceResult {\n /** Resource contents returned by the server. */\n contents: Array<{ uri: string; mimeType?: string; text?: string; blob?: string }>;\n}\n\n/**\n * Hook to read resources from the originating MCP server.\n *\n * Resources are proxied through the host. Use {@link useListServerResources}\n * to discover available resources first.\n *\n * @example\n * ```tsx\n * function VideoPlayer() {\n * const readServerResource = useReadServerResource();\n * const [src, setSrc] = useState<string>();\n *\n * const loadVideo = async (uri: string) => {\n * const result = await readServerResource({ uri });\n * const content = result?.contents[0];\n * if (content && 'blob' in content && content.blob) {\n * const binary = atob(content.blob);\n * const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));\n * const blob = new Blob([bytes], { type: content.mimeType });\n * setSrc(URL.createObjectURL(blob));\n * }\n * };\n *\n * return src ? <video src={src} controls /> : <button onClick={() => loadVideo('videos://intro')}>Load</button>;\n * }\n * ```\n */\nexport function useReadServerResource(): (\n params: ReadServerResourceParams\n) => Promise<ReadServerResourceResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: ReadServerResourceParams) => {\n if (!app) {\n console.warn('[useReadServerResource] App not connected');\n return undefined;\n }\n return app.readServerResource(params as Parameters<App['readServerResource']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type {\n RegisteredAppTool,\n AppToolCallback,\n StandardSchemaV1,\n} from '@modelcontextprotocol/ext-apps';\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport interface RegisterToolConfig {\n title?: string;\n description?: string;\n inputSchema?: StandardSchemaV1;\n outputSchema?: StandardSchemaV1;\n annotations?: ToolAnnotations;\n _meta?: Record<string, unknown>;\n}\n\nexport function useRegisterTool(): (\n name: string,\n config: RegisterToolConfig,\n cb: AppToolCallback<StandardSchemaV1 | undefined, StandardSchemaV1 | undefined>\n) => RegisteredAppTool | undefined {\n const app = useApp();\n return useCallback(\n (\n name: string,\n config: RegisterToolConfig,\n cb: AppToolCallback<StandardSchemaV1 | undefined, StandardSchemaV1 | undefined>\n ) => {\n if (!app) {\n console.warn('[useRegisterTool] App not connected');\n return undefined;\n }\n return app.registerTool(name, config, cb);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\nimport { useHostContext } from './use-host-context';\n\n/**\n * Display modes available for apps.\n */\nexport type AppDisplayMode = 'inline' | 'pip' | 'fullscreen';\n\n/**\n * Hook to request a display mode change.\n *\n * Returns a function to request display mode changes and the list of available modes.\n * Always check `availableModes` before requesting a mode change.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const { requestDisplayMode, availableModes } = useRequestDisplayMode();\n *\n * return (\n * <>\n * {availableModes?.includes('fullscreen') && (\n * <button onClick={() => requestDisplayMode('fullscreen')}>\n * Fullscreen\n * </button>\n * )}\n * {availableModes?.includes('pip') && (\n * <button onClick={() => requestDisplayMode('pip')}>\n * Picture-in-Picture\n * </button>\n * )}\n * </>\n * );\n * }\n * ```\n */\nexport function useRequestDisplayMode(): {\n /** Request a display mode change */\n requestDisplayMode: (mode: AppDisplayMode) => Promise<void>;\n /** List of display modes the host supports */\n availableModes: AppDisplayMode[] | undefined;\n} {\n const app = useApp();\n const hostContext = useHostContext();\n\n const requestDisplayMode = useCallback(\n async (mode: AppDisplayMode) => {\n if (!app) {\n console.warn('[useRequestDisplayMode] App not connected');\n return;\n }\n await app.requestDisplayMode({ mode });\n },\n [app]\n );\n\n return {\n requestDisplayMode,\n availableModes: hostContext?.availableDisplayModes as AppDisplayMode[] | undefined,\n };\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Hook to request the host to tear down this app.\n *\n * Sends a notification to the host requesting that it initiate teardown.\n * If the host approves, it will send the standard teardown request back\n * to the app (triggering any `useTeardown` callbacks) before unmounting.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const requestTeardown = useRequestTeardown();\n *\n * return (\n * <button onClick={() => requestTeardown()}>\n * Close App\n * </button>\n * );\n * }\n * ```\n */\nexport function useRequestTeardown(): () => Promise<void> {\n const app = useApp();\n return useCallback(async () => {\n if (!app) {\n console.warn('[useRequestTeardown] App not connected');\n return;\n }\n await app.requestTeardown();\n }, [app]);\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Log levels for structured logging.\n */\nexport type LogLevel = 'debug' | 'info' | 'warning' | 'error' | 'critical';\n\n/**\n * Parameters for sending a log message.\n */\nexport interface SendLogParams {\n /** Log level */\n level: LogLevel;\n /** Log data (string or object) */\n data: unknown;\n /** Optional logger name for categorization */\n logger?: string;\n}\n\n/**\n * Hook to send structured log messages to the host.\n *\n * Sends logs through the MCP protocol rather than just console.log.\n * Useful for debugging in production where console isn't accessible.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const sendLog = useSendLog();\n *\n * const handleAction = () => {\n * sendLog({ level: 'info', data: 'User clicked button' });\n * sendLog({\n * level: 'debug',\n * data: { action: 'click', target: 'submit' },\n * logger: 'analytics'\n * });\n * };\n *\n * return <button onClick={handleAction}>Click Me</button>;\n * }\n * ```\n */\nexport function useSendLog(): (params: SendLogParams) => void {\n const app = useApp();\n return useCallback(\n (params: SendLogParams) => {\n if (!app) {\n // Fall back to console when not connected\n const consoleFn =\n params.level === 'error' || params.level === 'critical'\n ? console.error\n : params.level === 'warning'\n ? console.warn\n : params.level === 'debug'\n ? console.debug\n : console.log;\n consoleFn(`[${params.logger ?? 'app'}]`, params.data);\n return;\n }\n app.sendLog(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Content item for a message.\n */\nexport interface MessageContent {\n type: 'text';\n text: string;\n}\n\n/**\n * Parameters for sending a message.\n */\nexport interface SendMessageParams {\n /** Role must be 'user' for MCP Apps */\n role: 'user';\n /** Content array for the message */\n content: MessageContent[];\n}\n\n/**\n * Hook to send follow-up messages to the conversation.\n *\n * Sends a message that appears in the conversation as if the user sent it.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const sendMessage = useSendMessage();\n *\n * const handleSubmit = async () => {\n * await sendMessage({\n * role: 'user',\n * content: [{ type: 'text', text: 'Please update the chart' }]\n * });\n * };\n *\n * return <button onClick={handleSubmit}>Request Update</button>;\n * }\n * ```\n */\nexport function useSendMessage(): (params: SendMessageParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: SendMessageParams) => {\n if (!app) {\n console.warn('[useSendMessage] App not connected');\n return;\n }\n await app.sendMessage(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\nexport function useSendToolListChanged(): () => Promise<void> {\n const app = useApp();\n return useCallback(async () => {\n if (!app) {\n console.warn('[useSendToolListChanged] App not connected');\n return;\n }\n await app.sendToolListChanged();\n }, [app]);\n}\n","import { useCallback } from 'react';\nimport type { McpUiUpdateModelContextRequest } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/** Parameters for updating model context — matches the MCP Apps SDK type. */\nexport type UpdateModelContextParams = McpUiUpdateModelContextRequest['params'];\n\n/**\n * Send model context updates to the host.\n *\n * Unlike `useAppState` (which automatically syncs structured state),\n * this hook gives direct control over when and what is sent to the\n * model context — including text content blocks.\n *\n * Each call overwrites the previous context. The host includes the\n * last update in the model's next turn.\n *\n * @example\n * ```tsx\n * import { useUpdateModelContext } from 'sunpeak';\n *\n * function MyResource() {\n * const updateModelContext = useUpdateModelContext();\n *\n * const handleSelect = (item: Item) => {\n * updateModelContext({\n * structuredContent: { selectedItem: item },\n * });\n * };\n * }\n * ```\n */\nexport function useUpdateModelContext(): (params: UpdateModelContextParams) => Promise<void> {\n const app = useApp();\n\n return useCallback(\n async (params: UpdateModelContextParams) => {\n if (!app) return;\n await app.updateModelContext(params);\n },\n [app]\n );\n}\n","import { useApp } from './use-app';\n\n/**\n * Host version information.\n */\nexport interface HostVersion {\n /** Name of the host application */\n name: string;\n /** Version of the host application */\n version: string;\n}\n\n/**\n * Host capabilities indicating what features are supported.\n */\nexport interface HostCapabilities {\n /** Whether the host supports calling server tools */\n serverTools?: boolean;\n /** Whether the host supports opening external links */\n openLinks?: boolean;\n /** Whether the host supports structured logging */\n logging?: boolean;\n /** Whether the host supports sending messages */\n messages?: boolean;\n /** Whether the host supports display mode changes */\n displayModes?: boolean;\n /** Additional capability flags */\n [key: string]: unknown;\n}\n\n/**\n * Hook to get information about the host application.\n *\n * Returns the host's version and capabilities. Use capabilities to check\n * what features are available before using them.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const { hostVersion, hostCapabilities } = useHostInfo();\n *\n * return (\n * <div>\n * <p>Running in: {hostVersion?.name} v{hostVersion?.version}</p>\n * {hostCapabilities?.serverTools && (\n * <button>Call Server Tool</button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useHostInfo(): {\n /** Host application version info */\n hostVersion: HostVersion | undefined;\n /** Host capabilities */\n hostCapabilities: HostCapabilities | undefined;\n} {\n const app = useApp();\n return {\n hostVersion: app?.getHostVersion() as HostVersion | undefined,\n hostCapabilities: app?.getHostCapabilities() as HostCapabilities | undefined,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Per-app subscriber registry.\n * The App class only supports a single onteardown callback,\n * so we multiplex it to allow multiple hook instances to subscribe.\n */\nconst registries = new WeakMap<App, Set<() => Promise<void> | void>>();\n\nfunction getRegistry(app: App): Set<() => Promise<void> | void> {\n let subs = registries.get(app);\n if (!subs) {\n subs = new Set();\n registries.set(app, subs);\n\n app.onteardown = async () => {\n for (const fn of subs!) await fn();\n return {};\n };\n }\n return subs;\n}\n\n/**\n * Hook to register a cleanup callback before the app is unmounted.\n *\n * The callback runs when the host signals teardown, before the iframe is destroyed.\n * Use this for cleanup that must complete before unmount (e.g., saving state).\n * Multiple components can safely call this hook — all callbacks will run.\n *\n * @param callback - Async function to run on teardown.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const [data, setData] = useState({});\n *\n * useTeardown(async () => {\n * await saveToServer(data);\n * });\n *\n * return <Editor data={data} onChange={setData} />;\n * }\n * ```\n */\nexport function useTeardown(callback: () => Promise<void> | void): void {\n const app = useApp();\n const callbackRef = useRef(callback);\n\n // Keep callback ref up to date\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (!app) return;\n\n const subs = getRegistry(app);\n const wrapper = () => callbackRef.current();\n subs.add(wrapper);\n\n return () => {\n subs.delete(wrapper);\n };\n }, [app]);\n}\n","import { useEffect } from 'react';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport interface AppTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n}\n\nexport interface AppToolsConfig {\n /** Tools this app provides to the host */\n tools: AppTool[];\n /**\n * Handler called when the host invokes one of this app's tools.\n * Return a CallToolResult with the tool's output.\n */\n onCallTool: (params: {\n name: string;\n arguments?: Record<string, unknown>;\n }) => CallToolResult | Promise<CallToolResult>;\n}\n\n/**\n * Register tools that this app provides to the host.\n *\n * This enables bidirectional tool calling: the host can call tools\n * defined by the app, in addition to the app calling server tools.\n *\n * @example\n * ```tsx\n * import { useAppTools } from 'sunpeak';\n *\n * function MyResource() {\n * useAppTools({\n * tools: [\n * { name: 'get-selection', description: 'Get the current selection' },\n * ],\n * onCallTool: async ({ name, arguments: args }) => {\n * if (name === 'get-selection') {\n * return { content: [{ type: 'text', text: selectedText }] };\n * }\n * return { content: [], isError: true };\n * },\n * });\n * }\n * ```\n */\nexport function useAppTools(config: AppToolsConfig): void {\n const app = useApp();\n\n useEffect(() => {\n if (!app) return;\n\n // Advertise app-provided tools to the host. Full tool metadata (description,\n // schema) is registered server-side via registerAppTool; this provides\n // the runtime tool list to the host's listTools request.\n // eslint-disable-next-line react-hooks/immutability\n app.onlisttools = () => {\n return Promise.resolve({\n tools: config.tools.map((t) => ({\n name: t.name,\n ...(t.description ? { description: t.description } : {}),\n inputSchema: {\n type: 'object' as const,\n ...t.inputSchema,\n },\n })),\n });\n };\n\n app.oncalltool = (params) => {\n return Promise.resolve(config.onCallTool(params));\n };\n }, [app, config]);\n}\n","import { useCallback, useEffect, useRef, useState, type SetStateAction } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * State management with automatic sync to host via updateModelContext.\n *\n * This hook provides React-like state management that automatically sends\n * state updates to the host via `app.updateModelContext()`. The host can\n * then include this state in the model's context for the next message.\n *\n * @example Basic usage\n * ```tsx\n * import { useAppState } from 'sunpeak';\n *\n * function MyResource() {\n * const [state, setState] = useAppState({ count: 0 });\n *\n * return (\n * <button onClick={() => setState(prev => ({ ...prev, count: prev.count + 1 }))}>\n * Count: {state.count}\n * </button>\n * );\n * }\n * ```\n *\n * @example With typed state\n * ```tsx\n * interface MyState {\n * selectedId: string | null;\n * items: string[];\n * }\n *\n * const [state, setState] = useAppState<MyState>({ selectedId: null, items: [] });\n * ```\n *\n * @param defaultState - Initial state value.\n * @returns A tuple of [state, setState] similar to React's useState.\n */\nexport function useAppState<T>(defaultState: T): readonly [T, (state: SetStateAction<T>) => void] {\n const app = useApp();\n const [state, _setState] = useState<T>(defaultState);\n const pendingSync = useRef<T | null>(null);\n\n // Listen for debug state injection from inspector (sunpeak/injectState message).\n // This is a debug feature that allows the inspector to inject state changes\n // without going through the normal MCP Apps protocol flow.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const handler = (event: MessageEvent) => {\n // Only accept messages from parent (inspector)\n if (event.source !== window.parent) return;\n\n const data = event.data;\n if (\n data &&\n typeof data === 'object' &&\n data.method === 'sunpeak/injectState' &&\n data.params?.state != null\n ) {\n _setState(data.params.state as T);\n }\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, []);\n\n // Flush pending state to host after render completes\n useEffect(() => {\n if (pendingSync.current != null && app) {\n const value = pendingSync.current;\n pendingSync.current = null;\n app\n .updateModelContext({\n structuredContent: value,\n })\n .catch(() => {\n // Silently ignore — host may not support updateModelContext\n });\n }\n });\n\n const setState = useCallback((action: SetStateAction<T>) => {\n _setState((prev) => {\n const next = typeof action === 'function' ? (action as (prev: T) => T)(prev) : action;\n pendingSync.current = next;\n return next;\n });\n }, []);\n\n return [state, setState] as const;\n}\n","function matchMediaQuery(query: string) {\n return window.matchMedia(query).matches;\n}\n\nfunction createMediaQueryFn(query: string) {\n return () => matchMediaQuery(query);\n}\n\nexport const prefersReducedMotion = createMediaQueryFn('(prefers-reduced-motion: reduce)');\n\nexport const isPrimarilyTouchDevice = createMediaQueryFn('(pointer: coarse)');\n\nexport const isHoverAvailable = createMediaQueryFn('(hover: hover)');\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["i","J.union","J.literal","J.record","J.string","J.undefined","J.object","A","J.boolean","C","P","J.array","J.number","J.unknown","n","v","T","g","s","J.never","FJ","IJ","r","DJ","f","EJ","UJ","d","l","u","F","E","I","U","wQ","kQ","JK","eJ","t","M"],"sources":["../../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.7.2_@modelcontextprotocol+sdk@1.29.0_zod@4.4.3__react-_f5b843da9146ebea748e10ad8dfce46a/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js","../src/hooks/use-host-context.ts","../src/hooks/use-tool-data.ts","../src/hooks/use-device-capabilities.ts","../src/hooks/use-display-mode.ts","../src/hooks/use-locale.ts","../src/hooks/use-platform.ts","../src/hooks/use-safe-area.ts","../src/hooks/use-styles.ts","../src/hooks/use-theme.ts","../src/hooks/use-time-zone.ts","../src/hooks/use-tool-info.ts","../src/hooks/use-user-agent.ts","../src/hooks/use-viewport.ts","../src/hooks/use-mobile.ts","../src/hooks/safe-area.tsx","../src/hooks/use-call-server-tool.ts","../src/hooks/use-create-sampling-message.ts","../src/hooks/use-download-file.ts","../src/hooks/use-list-server-resources.ts","../src/hooks/use-open-link.ts","../src/hooks/use-read-server-resource.ts","../src/hooks/use-register-tool.ts","../src/hooks/use-request-display-mode.ts","../src/hooks/use-request-teardown.ts","../src/hooks/use-send-log.ts","../src/hooks/use-send-message.ts","../src/hooks/use-send-tool-list-changed.ts","../src/hooks/use-update-model-context.ts","../src/hooks/use-host-info.ts","../src/hooks/use-teardown.ts","../src/hooks/use-app-tools.ts","../src/hooks/use-app-state.ts","../src/lib/media-queries.ts"],"sourcesContent":["var JJ=((K)=>typeof require<\"u\"?require:typeof Proxy<\"u\"?new Proxy(K,{get:(Q,X)=>(typeof require<\"u\"?require:Q)[X]}):K)(function(K){if(typeof require<\"u\")return require.apply(this,arguments);throw Error('Dynamic require of \"'+K+'\" is not supported')});import{useEffect as sJ,useState as c}from\"react\";import{mergeCapabilities as uJ}from\"@modelcontextprotocol/sdk/shared/protocol.js\";import{CallToolRequestSchema as hJ,CallToolResultSchema as mJ,CreateMessageResultSchema as cJ,CreateMessageResultWithToolsSchema as rJ,EmptyResultSchema as lJ,ListResourcesResultSchema as iJ,ListToolsRequestSchema as pJ,PingRequestSchema as nJ,ReadResourceResultSchema as oJ}from\"@modelcontextprotocol/sdk/types.js\";import{Protocol as KJ}from\"@modelcontextprotocol/sdk/shared/protocol.js\";class z extends KJ{_registeredMethods=new Set;_eventSlots=new Map;onEventDispatch(K,Q){}_ensureEventSlot(K){let Q=this._eventSlots.get(K);if(!Q){let X=this.eventSchemas[K];if(!X)throw Error(`Unknown event: ${String(K)}`);Q={listeners:[]},this._eventSlots.set(K,Q);let Y=X.shape.method.value;this._registeredMethods.add(Y);let Z=Q;super.setNotificationHandler(X,($)=>{let G=$.params;this.onEventDispatch(K,G),Z.onHandler?.(G);for(let j of[...Z.listeners])j(G)})}return Q}setEventHandler(K,Q){let X=this._ensureEventSlot(K);if(X.onHandler&&Q)console.warn(`[MCP Apps] on${String(K)} handler replaced. Use addEventListener(\"${String(K)}\", …) to add multiple listeners without replacing.`);X.onHandler=Q}getEventHandler(K){return this._eventSlots.get(K)?.onHandler}addEventListener(K,Q){this._ensureEventSlot(K).listeners.push(Q)}removeEventListener(K,Q){let X=this._eventSlots.get(K);if(!X)return;let Y=X.listeners.indexOf(Q);if(Y!==-1)X.listeners.splice(Y,1)}setRequestHandler=(K,Q)=>{this._assertMethodNotRegistered(K,\"setRequestHandler\"),super.setRequestHandler(K,Q)};setNotificationHandler=(K,Q)=>{this._assertMethodNotRegistered(K,\"setNotificationHandler\"),super.setNotificationHandler(K,Q)};warnIfRequestHandlerReplaced(K,Q,X){if(Q&&X)console.warn(`[MCP Apps] ${K} handler replaced. Previous handler will no longer be called.`)}replaceRequestHandler=(K,Q)=>{let X=K.shape.method.value;this._registeredMethods.add(X),super.setRequestHandler(K,Q)};_assertMethodNotRegistered(K,Q){let X=K.shape.method.value;if(this._registeredMethods.has(X))throw Error(`Handler for \"${X}\" already registered (via ${Q}). Use addEventListener() to attach multiple listeners, or the on* setter for replace semantics.`);this._registeredMethods.add(X)}}import{JSONRPCMessageSchema as PJ}from\"@modelcontextprotocol/sdk/types.js\";var w=\"2026-01-26\",QJ=\"ui/open-link\",XJ=\"ui/download-file\",YJ=\"ui/message\",ZJ=\"ui/notifications/sandbox-proxy-ready\",$J=\"ui/notifications/sandbox-resource-ready\",GJ=\"ui/notifications/size-changed\",jJ=\"ui/notifications/tool-input\",H=\"ui/notifications/tool-input-partial\",WJ=\"ui/notifications/tool-result\",LJ=\"ui/notifications/tool-cancelled\",NJ=\"ui/notifications/host-context-changed\",BJ=\"ui/notifications/request-teardown\",VJ=\"ui/resource-teardown\",_J=\"ui/initialize\",OJ=\"ui/notifications/initialized\",qJ=\"ui/request-display-mode\";class B{eventTarget;eventSource;messageListener;constructor(K=window.parent,Q){this.eventTarget=K;this.eventSource=Q;this.messageListener=(X)=>{if(Q&&X.source!==this.eventSource){console.debug(\"Ignoring message from unknown source\",X);return}let Y=PJ.safeParse(X.data);if(Y.success)console.debug(\"Parsed message\",Y.data),this.onmessage?.(Y.data);else if(X.data?.jsonrpc!==\"2.0\")console.debug(\"Ignoring non-JSON-RPC message\",Y.error.message,X);else console.error(\"Failed to parse message\",Y.error.message,X),this.onerror?.(Error(\"Invalid JSON-RPC message received: \"+Y.error.message))}}async start(){window.addEventListener(\"message\",this.messageListener)}async send(K,Q){if(K.method!==H)console.debug(\"Sending message\",K);this.eventTarget.postMessage(K,\"*\")}async close(){window.removeEventListener(\"message\",this.messageListener),this.onclose?.()}onclose;onerror;onmessage;sessionId;setProtocolVersion}import{z as J}from\"zod/v4\";import{ContentBlockSchema as r,CallToolResultSchema as DJ,EmbeddedResourceSchema as FJ,ImplementationSchema as l,RequestIdSchema as EJ,ResourceLinkSchema as IJ,ToolSchema as UJ}from\"@modelcontextprotocol/sdk/types.js\";var i=J.union([J.literal(\"light\"),J.literal(\"dark\")]).describe(\"Color theme preference for the host environment.\"),V=J.union([J.literal(\"inline\"),J.literal(\"fullscreen\"),J.literal(\"pip\")]).describe(\"Display mode for UI presentation.\"),RJ=J.union([J.literal(\"--color-background-primary\"),J.literal(\"--color-background-secondary\"),J.literal(\"--color-background-tertiary\"),J.literal(\"--color-background-inverse\"),J.literal(\"--color-background-ghost\"),J.literal(\"--color-background-info\"),J.literal(\"--color-background-danger\"),J.literal(\"--color-background-success\"),J.literal(\"--color-background-warning\"),J.literal(\"--color-background-disabled\"),J.literal(\"--color-text-primary\"),J.literal(\"--color-text-secondary\"),J.literal(\"--color-text-tertiary\"),J.literal(\"--color-text-inverse\"),J.literal(\"--color-text-ghost\"),J.literal(\"--color-text-info\"),J.literal(\"--color-text-danger\"),J.literal(\"--color-text-success\"),J.literal(\"--color-text-warning\"),J.literal(\"--color-text-disabled\"),J.literal(\"--color-border-primary\"),J.literal(\"--color-border-secondary\"),J.literal(\"--color-border-tertiary\"),J.literal(\"--color-border-inverse\"),J.literal(\"--color-border-ghost\"),J.literal(\"--color-border-info\"),J.literal(\"--color-border-danger\"),J.literal(\"--color-border-success\"),J.literal(\"--color-border-warning\"),J.literal(\"--color-border-disabled\"),J.literal(\"--color-ring-primary\"),J.literal(\"--color-ring-secondary\"),J.literal(\"--color-ring-inverse\"),J.literal(\"--color-ring-info\"),J.literal(\"--color-ring-danger\"),J.literal(\"--color-ring-success\"),J.literal(\"--color-ring-warning\"),J.literal(\"--font-sans\"),J.literal(\"--font-mono\"),J.literal(\"--font-weight-normal\"),J.literal(\"--font-weight-medium\"),J.literal(\"--font-weight-semibold\"),J.literal(\"--font-weight-bold\"),J.literal(\"--font-text-xs-size\"),J.literal(\"--font-text-sm-size\"),J.literal(\"--font-text-md-size\"),J.literal(\"--font-text-lg-size\"),J.literal(\"--font-heading-xs-size\"),J.literal(\"--font-heading-sm-size\"),J.literal(\"--font-heading-md-size\"),J.literal(\"--font-heading-lg-size\"),J.literal(\"--font-heading-xl-size\"),J.literal(\"--font-heading-2xl-size\"),J.literal(\"--font-heading-3xl-size\"),J.literal(\"--font-text-xs-line-height\"),J.literal(\"--font-text-sm-line-height\"),J.literal(\"--font-text-md-line-height\"),J.literal(\"--font-text-lg-line-height\"),J.literal(\"--font-heading-xs-line-height\"),J.literal(\"--font-heading-sm-line-height\"),J.literal(\"--font-heading-md-line-height\"),J.literal(\"--font-heading-lg-line-height\"),J.literal(\"--font-heading-xl-line-height\"),J.literal(\"--font-heading-2xl-line-height\"),J.literal(\"--font-heading-3xl-line-height\"),J.literal(\"--border-radius-xs\"),J.literal(\"--border-radius-sm\"),J.literal(\"--border-radius-md\"),J.literal(\"--border-radius-lg\"),J.literal(\"--border-radius-xl\"),J.literal(\"--border-radius-full\"),J.literal(\"--border-width-regular\"),J.literal(\"--shadow-hairline\"),J.literal(\"--shadow-sm\"),J.literal(\"--shadow-md\"),J.literal(\"--shadow-lg\")]).describe(\"CSS variable keys available to MCP apps for theming.\"),MJ=J.record(RJ.describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`),J.union([J.string(),J.undefined()]).describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`)).describe(`Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses \\`Record<K, string | undefined>\\` rather than \\`Partial<Record<K, string>>\\`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.`),zJ=J.object({method:J.literal(\"ui/open-link\"),params:J.object({url:J.string().describe(\"URL to open in the host's browser\")})}),A=J.object({isError:J.boolean().optional().describe(\"True if the host failed to open the URL (e.g., due to security policy).\")}).passthrough(),k=J.object({isError:J.boolean().optional().describe(\"True if the download failed (e.g., user cancelled or host denied).\")}).passthrough(),C=J.object({isError:J.boolean().optional().describe(\"True if the host rejected or failed to deliver the message.\")}).passthrough(),wJ=J.object({method:J.literal(\"ui/notifications/sandbox-proxy-ready\"),params:J.object({})}),P=J.object({connectDomains:J.array(J.string()).optional().describe(`Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP \\`connect-src\\` directive\n- Empty or omitted → no network connections (secure default)`),resourceDomains:J.array(J.string()).optional().describe(\"Origins for static resources (images, scripts, stylesheets, fonts, media).\\n\\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\\n- Wildcard subdomains supported: `https://*.example.com`\\n- Empty or omitted → no network resources (secure default)\"),frameDomains:J.array(J.string()).optional().describe(\"Origins for nested iframes.\\n\\n- Maps to CSP `frame-src` directive\\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)\"),baseUriDomains:J.array(J.string()).optional().describe(\"Allowed base URIs for the document.\\n\\n- Maps to CSP `base-uri` directive\\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)\")}),D=J.object({camera:J.object({}).optional().describe(\"Request camera access.\\n\\nMaps to Permission Policy `camera` feature.\"),microphone:J.object({}).optional().describe(\"Request microphone access.\\n\\nMaps to Permission Policy `microphone` feature.\"),geolocation:J.object({}).optional().describe(\"Request geolocation access.\\n\\nMaps to Permission Policy `geolocation` feature.\"),clipboardWrite:J.object({}).optional().describe(\"Request clipboard write access.\\n\\nMaps to Permission Policy `clipboard-write` feature.\")}),HJ=J.object({method:J.literal(\"ui/notifications/size-changed\"),params:J.object({width:J.number().optional().describe(\"New width in pixels.\"),height:J.number().optional().describe(\"New height in pixels.\")})}),S=J.object({method:J.literal(\"ui/notifications/tool-input\"),params:J.object({arguments:J.record(J.string(),J.unknown().describe(\"Complete tool call arguments as key-value pairs.\")).optional().describe(\"Complete tool call arguments as key-value pairs.\")})}),b=J.object({method:J.literal(\"ui/notifications/tool-input-partial\"),params:J.object({arguments:J.record(J.string(),J.unknown().describe(\"Partial tool call arguments (incomplete, may change).\")).optional().describe(\"Partial tool call arguments (incomplete, may change).\")})}),x=J.object({method:J.literal(\"ui/notifications/tool-cancelled\"),params:J.object({reason:J.string().optional().describe('Optional reason for the cancellation (e.g., \"user action\", \"timeout\").')})}),p=J.object({fonts:J.string().optional()}),n=J.object({variables:MJ.optional().describe(\"CSS variables for theming the app.\"),css:p.optional().describe(\"CSS blocks that apps can inject.\")}),v=J.object({method:J.literal(\"ui/resource-teardown\"),params:J.object({})}),TJ=J.record(J.string(),J.unknown()),T=J.object({text:J.object({}).optional().describe(\"Host supports text content blocks.\"),image:J.object({}).optional().describe(\"Host supports image content blocks.\"),audio:J.object({}).optional().describe(\"Host supports audio content blocks.\"),resource:J.object({}).optional().describe(\"Host supports resource content blocks.\"),resourceLink:J.object({}).optional().describe(\"Host supports resource link content blocks.\"),structuredContent:J.object({}).optional().describe(\"Host supports structured content.\")}),AJ=J.object({method:J.literal(\"ui/notifications/request-teardown\"),params:J.object({}).optional()}),o=J.object({experimental:J.object({}).optional().describe(\"Experimental features (structure TBD).\"),openLinks:J.object({}).optional().describe(\"Host supports opening external URLs.\"),downloadFile:J.object({}).optional().describe(\"Host supports file downloads via ui/download-file.\"),serverTools:J.object({listChanged:J.boolean().optional().describe(\"Host supports tools/list_changed notifications.\")}).optional().describe(\"Host can proxy tool calls to the MCP server.\"),serverResources:J.object({listChanged:J.boolean().optional().describe(\"Host supports resources/list_changed notifications.\")}).optional().describe(\"Host can proxy resource reads to the MCP server.\"),logging:J.object({}).optional().describe(\"Host accepts log messages.\"),sandbox:J.object({permissions:D.optional().describe(\"Permissions granted by the host (camera, microphone, geolocation).\"),csp:P.optional().describe(\"CSP domains approved by the host.\")}).optional().describe(\"Sandbox configuration applied by the host.\"),updateModelContext:T.optional().describe(\"Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.\"),message:T.optional().describe(\"Host supports receiving content messages (ui/message) from the view.\"),sampling:J.object({tools:J.object({}).optional().describe(\"Host supports tool use via `tools` and `toolChoice` parameters.\")}).optional().describe(\"Host supports LLM sampling (sampling/createMessage) from the view.\\nMirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.\")}),a=J.object({experimental:J.object({}).optional().describe(\"Experimental features (structure TBD).\"),tools:J.object({listChanged:J.boolean().optional().describe(\"App supports tools/list_changed notifications.\")}).optional().describe(\"App exposes MCP-style tools that the host can call.\"),availableDisplayModes:J.array(V).optional().describe(\"Display modes the app supports.\")}),kJ=J.object({method:J.literal(\"ui/notifications/initialized\"),params:J.object({}).optional()}),CJ=J.object({csp:P.optional().describe(\"Content Security Policy configuration for UI resources.\"),permissions:D.optional().describe(\"Sandbox permissions requested by the UI resource.\"),domain:J.string().optional().describe(`Dedicated origin for view sandbox.\n\nUseful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.\n\n**Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:\n- Hash-based subdomains (e.g., \\`{hash}.claudemcpcontent.com\\`)\n- URL-derived subdomains (e.g., \\`www-example-com.oaiusercontent.com\\`)\n\nIf omitted, host uses default sandbox origin (typically per-conversation).`),prefersBorder:J.boolean().optional().describe(`Visual boundary preference - true if view prefers a visible border.\n\nBoolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.\n\n- \\`true\\`: request visible border + background\n- \\`false\\`: request no visible border + background\n- omitted: host decides border`)}),SJ=J.object({method:J.literal(\"ui/request-display-mode\"),params:J.object({mode:V.describe(\"The display mode being requested.\")})}),g=J.object({mode:V.describe(\"The display mode that was actually set. May differ from requested if not supported.\")}).passthrough(),s=J.union([J.literal(\"model\"),J.literal(\"app\")]).describe(\"Tool visibility scope - who can access the tool.\"),bJ=J.object({resourceUri:J.string().optional(),visibility:J.array(s).optional().describe(`Who can access this tool. Default: [\"model\", \"app\"]\n- \"model\": Tool visible to and callable by the agent\n- \"app\": Tool callable by the app from this server only`),csp:J.never().optional(),permissions:J.never().optional()}),_K=J.object({mimeTypes:J.array(J.string()).optional().describe('Array of supported MIME types for UI resources.\\nMust include `\"text/html;profile=mcp-app\"` for MCP Apps support.')}),xJ=J.object({method:J.literal(\"ui/download-file\"),params:J.object({contents:J.array(J.union([FJ,IJ])).describe(\"Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.\")})}),vJ=J.object({method:J.literal(\"ui/message\"),params:J.object({role:J.literal(\"user\").describe('Message role, currently only \"user\" is supported.'),content:J.array(r).describe(\"Message content blocks (text, image, etc.).\")})}),gJ=J.object({method:J.literal(\"ui/notifications/sandbox-resource-ready\"),params:J.object({html:J.string().describe(\"HTML content to load into the inner iframe.\"),sandbox:J.string().optional().describe(\"Optional override for the inner iframe's sandbox attribute.\"),csp:P.optional().describe(\"CSP configuration from resource metadata.\"),permissions:D.optional().describe(\"Sandbox permissions from resource metadata.\")})}),y=J.object({method:J.literal(\"ui/notifications/tool-result\"),params:DJ.describe(\"Standard MCP tool execution result.\")}),f=J.object({toolInfo:J.object({id:EJ.optional().describe(\"JSON-RPC id of the tools/call request.\"),tool:UJ.describe(\"Tool definition including name, inputSchema, etc.\")}).optional().describe(\"Metadata of the tool call that instantiated this App.\"),theme:i.optional().describe(\"Current color theme preference.\"),styles:n.optional().describe(\"Style configuration for theming the app.\"),displayMode:V.optional().describe(\"How the UI is currently displayed.\"),availableDisplayModes:J.array(V).optional().describe(\"Display modes the host supports.\"),containerDimensions:J.union([J.object({height:J.number().describe(\"Fixed container height in pixels.\")}),J.object({maxHeight:J.union([J.number(),J.undefined()]).optional().describe(\"Maximum container height in pixels.\")})]).and(J.union([J.object({width:J.number().describe(\"Fixed container width in pixels.\")}),J.object({maxWidth:J.union([J.number(),J.undefined()]).optional().describe(\"Maximum container width in pixels.\")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other\ncontainer holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:J.string().optional().describe(\"User's language and region preference in BCP 47 format.\"),timeZone:J.string().optional().describe(\"User's timezone in IANA format.\"),userAgent:J.string().optional().describe(\"Host application identifier.\"),platform:J.union([J.literal(\"web\"),J.literal(\"desktop\"),J.literal(\"mobile\")]).optional().describe(\"Platform type for responsive design decisions.\"),deviceCapabilities:J.object({touch:J.boolean().optional().describe(\"Whether the device supports touch input.\"),hover:J.boolean().optional().describe(\"Whether the device supports hover interactions.\")}).optional().describe(\"Device input capabilities.\"),safeAreaInsets:J.object({top:J.number().describe(\"Top safe area inset in pixels.\"),right:J.number().describe(\"Right safe area inset in pixels.\"),bottom:J.number().describe(\"Bottom safe area inset in pixels.\"),left:J.number().describe(\"Left safe area inset in pixels.\")}).optional().describe(\"Mobile safe area boundaries in pixels.\")}).passthrough(),d=J.object({method:J.literal(\"ui/notifications/host-context-changed\"),params:f.describe(\"Partial context update containing only changed fields.\")}),yJ=J.object({method:J.literal(\"ui/update-model-context\"),params:J.object({content:J.array(r).optional().describe(\"Context content blocks (text, image, etc.).\"),structuredContent:J.record(J.string(),J.unknown().describe(\"Structured content for machine-readable context data.\")).optional().describe(\"Structured content for machine-readable context data.\")})}),fJ=J.object({method:J.literal(\"ui/initialize\"),params:J.object({appInfo:l.describe(\"App identification (name and version).\"),appCapabilities:a.describe(\"Features and capabilities this app provides.\"),protocolVersion:J.string().describe(\"Protocol version this app supports.\")})}),u=J.object({protocolVersion:J.string().describe('Negotiated protocol version string (e.g., \"2025-11-21\").'),hostInfo:l.describe(\"Host application identification and version.\"),hostCapabilities:o.describe(\"Features and capabilities provided by the host.\"),hostContext:f.describe(\"Rich context about the host environment.\")}).passthrough();var dJ={target:\"draft-2020-12\"};async function h(K,Q){let X=K[\"~standard\"];if(X.jsonSchema)return X.jsonSchema[Q](dJ);if(X.vendor===\"zod\"){let{z:Y}=await import(\"zod/v4\");return Y.toJSONSchema(K,{io:Q})}throw Error(`Schema (vendor: ${X.vendor}) does not implement Standard JSON Schema (~standard.jsonSchema). Use a library that does (zod v4, ArkType, Valibot) or wrap your schema accordingly.`)}async function m(K,Q,X=\"\"){let Y=await K[\"~standard\"].validate(Q);if(Y.issues){let Z=Y.issues.map(($)=>{let G=$.path?.map((j)=>typeof j===\"object\"?j.key:j).join(\".\");return G?`${G}: ${$.message}`:$.message}).join(\"; \");throw Error(X+Z)}return Y.value}import{z as aJ}from\"zod/v4\";function F(){let K=document.documentElement.getAttribute(\"data-theme\");if(K===\"dark\"||K===\"light\")return K;return document.documentElement.classList.contains(\"dark\")?\"dark\":\"light\"}function E(K){let Q=document.documentElement;Q.setAttribute(\"data-theme\",K),Q.style.colorScheme=K}function I(K,Q=document.documentElement){for(let[X,Y]of Object.entries(K))if(Y!==void 0)Q.style.setProperty(X,Y)}function U(K){if(document.getElementById(\"__mcp-host-fonts\"))return;let X=document.createElement(\"style\");X.id=\"__mcp-host-fonts\",X.textContent=K,document.head.appendChild(X)}var NQ=\"ui/resourceUri\",BQ=\"text/html;profile=mcp-app\";class R extends z{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;_registeredTools={};_initializedSent=!1;_assertInitialized(K){if(this._initializedSent)return;let Q=`[ext-apps] App.${K}() called before connect() completed the ui/initialize handshake. Await app.connect() before calling this method, or move data loading to an ontoolresult handler.`;if(this.options?.strict)throw Error(Q);console.warn(`${Q}. This will throw in a future release.`)}eventSchemas={toolinput:S,toolinputpartial:b,toolresult:y,toolcancelled:x,hostcontextchanged:d};static ONE_SHOT_EVENTS=new Set([\"toolinput\",\"toolinputpartial\",\"toolresult\",\"toolcancelled\"]);_everHadListener=new Set;_assertHandlerTiming(K){if(!R.ONE_SHOT_EVENTS.has(K)||this._everHadListener.has(K))return;if(this._everHadListener.add(K),!this._initializedSent)return;let Q=`[ext-apps] \"${String(K)}\" handler registered after connect() completed the ui/initialize handshake. The host may have already sent this notification. Register handlers before calling app.connect().`;if(this.options?.strict)throw Error(Q);console.warn(Q)}setEventHandler(K,Q){if(Q)this._assertHandlerTiming(K);super.setEventHandler(K,Q)}addEventListener(K,Q){this._assertHandlerTiming(K),super.addEventListener(K,Q)}onEventDispatch(K,Q){if(K===\"hostcontextchanged\")this._hostContext={...this._hostContext,...Q}}constructor(K,Q={},X={autoResize:!0}){super(X);this._appInfo=K;this._capabilities=Q;this.options=X;if(!X.allowUnsafeEval)aJ.config({jitless:!0});this.setRequestHandler(nJ,(Y)=>{return console.log(\"Received ping:\",Y.params),{}}),this.setEventHandler(\"hostcontextchanged\",void 0)}registerCapabilities(K){if(this.transport)throw Error(\"Cannot register capabilities after transport is established\");this._capabilities=uJ(this._capabilities,K)}registerTool(K,Q,X){if(this._registeredTools[K])throw Error(`Tool ${K} is already registered`);let Y=this,Z=()=>{if(Y._initializedSent&&Y._capabilities.tools?.listChanged)Y.sendToolListChanged()},$=Q.inputSchema!==void 0,G={title:Q.title,description:Q.description,inputSchema:Q.inputSchema,outputSchema:Q.outputSchema,annotations:Q.annotations,_meta:Q._meta,enabled:!0,enable(){this.enabled=!0,Z()},disable(){this.enabled=!1,Z()},update(j){Object.assign(this,j),Z()},remove(){if(Y._registeredTools[K]!==G)return;delete Y._registeredTools[K],Z()},handler:async(j,W)=>{if(!G.enabled)throw Error(`Tool ${K} is disabled`);let L;if($){let _=G.inputSchema,O=_?await m(_,j??{},`Invalid input for tool ${K}: `):j??{};L=await X(O,W)}else L=await X(W);if(G.outputSchema&&!L.isError)L.structuredContent=await m(G.outputSchema,L.structuredContent,`Invalid output for tool ${K}: `);return L}};if(this._registeredTools[K]=G,!this._capabilities.tools&&!this.transport)this.registerCapabilities({tools:{listChanged:!0}});return this.ensureToolHandlersInitialized(),Z(),G}_toolHandlersInitialized=!1;ensureToolHandlersInitialized(){if(this._toolHandlersInitialized)return;this._toolHandlersInitialized=!0,this.oncalltool=async(K,Q)=>{let X=this._registeredTools[K.name];if(!X)throw Error(`Tool ${K.name} not found`);return X.handler(K.arguments,Q)},this.onlisttools=async(K,Q)=>{return{tools:await Promise.all(Object.entries(this._registeredTools).filter(([Y,Z])=>Z.enabled).map(async([Y,Z])=>{let $={name:Y,title:Z.title,description:Z.description,inputSchema:Z.inputSchema?await h(Z.inputSchema,\"input\"):{type:\"object\",properties:{}}};if(Z.outputSchema)$.outputSchema=await h(Z.outputSchema,\"output\");if(Z.annotations)$.annotations=Z.annotations;if(Z._meta)$._meta=Z._meta;return $}))}}}async sendToolListChanged(K={}){this._assertInitialized(\"sendToolListChanged\"),await this.notification({method:\"notifications/tools/list_changed\",params:K})}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}get ontoolinput(){return this.getEventHandler(\"toolinput\")}set ontoolinput(K){this.setEventHandler(\"toolinput\",K)}get ontoolinputpartial(){return this.getEventHandler(\"toolinputpartial\")}set ontoolinputpartial(K){this.setEventHandler(\"toolinputpartial\",K)}get ontoolresult(){return this.getEventHandler(\"toolresult\")}set ontoolresult(K){this.setEventHandler(\"toolresult\",K)}get ontoolcancelled(){return this.getEventHandler(\"toolcancelled\")}set ontoolcancelled(K){this.setEventHandler(\"toolcancelled\",K)}get onhostcontextchanged(){return this.getEventHandler(\"hostcontextchanged\")}set onhostcontextchanged(K){this.setEventHandler(\"hostcontextchanged\",K)}_onteardown;get onteardown(){return this._onteardown}set onteardown(K){this.warnIfRequestHandlerReplaced(\"onteardown\",this._onteardown,K),this._onteardown=K,this.replaceRequestHandler(v,(Q,X)=>{if(!this._onteardown)throw Error(\"No onteardown handler set\");return this._onteardown(Q.params,X)})}_oncalltool;get oncalltool(){return this._oncalltool}set oncalltool(K){this.warnIfRequestHandlerReplaced(\"oncalltool\",this._oncalltool,K),this._oncalltool=K,this.replaceRequestHandler(hJ,(Q,X)=>{if(!this._oncalltool)throw Error(\"No oncalltool handler set\");return this._oncalltool(Q.params,X)})}_onlisttools;get onlisttools(){return this._onlisttools}set onlisttools(K){this.warnIfRequestHandlerReplaced(\"onlisttools\",this._onlisttools,K),this._onlisttools=K,this.replaceRequestHandler(pJ,(Q,X)=>{if(!this._onlisttools)throw Error(\"No onlisttools handler set\");return this._onlisttools(Q.params,X)})}assertCapabilityForMethod(K){switch(K){case\"sampling/createMessage\":if(!this._hostCapabilities?.sampling)throw Error(`Host does not support sampling (required for ${K})`);break}}assertRequestHandlerCapability(K){switch(K){case\"tools/call\":case\"tools/list\":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${K})`);return;case\"ping\":case\"ui/resource-teardown\":return;default:throw Error(`No handler for method ${K} registered`)}}assertNotificationCapability(K){}assertTaskCapability(K){throw Error(\"Tasks are not supported in MCP Apps\")}assertTaskHandlerCapability(K){throw Error(\"Task handlers are not supported in MCP Apps\")}async callServerTool(K,Q){if(this._assertInitialized(\"callServerTool\"),typeof K===\"string\")throw Error(`callServerTool() expects an object as its first argument, but received a string (\"${K}\"). Did you mean: callServerTool({ name: \"${K}\", arguments: { ... } })?`);return await this.request({method:\"tools/call\",params:K},mJ,{onprogress:()=>{},resetTimeoutOnProgress:!0,...Q})}async readServerResource(K,Q){return this._assertInitialized(\"readServerResource\"),await this.request({method:\"resources/read\",params:K},oJ,Q)}async listServerResources(K,Q){return this._assertInitialized(\"listServerResources\"),await this.request({method:\"resources/list\",params:K},iJ,Q)}async createSamplingMessage(K,Q){this._assertInitialized(\"createSamplingMessage\");let X=K.tools?rJ:cJ;return await this.request({method:\"sampling/createMessage\",params:K},X,Q)}sendMessage(K,Q){return this._assertInitialized(\"sendMessage\"),this.request({method:\"ui/message\",params:K},C,Q)}sendLog(K){return this.notification({method:\"notifications/message\",params:K})}updateModelContext(K,Q){return this._assertInitialized(\"updateModelContext\"),this.request({method:\"ui/update-model-context\",params:K},lJ,Q)}openLink(K,Q){return this._assertInitialized(\"openLink\"),this.request({method:\"ui/open-link\",params:K},A,Q)}sendOpenLink=this.openLink;downloadFile(K,Q){return this._assertInitialized(\"downloadFile\"),this.request({method:\"ui/download-file\",params:K},k,Q)}requestTeardown(K={}){return this.notification({method:\"ui/notifications/request-teardown\",params:K})}requestDisplayMode(K,Q){return this._assertInitialized(\"requestDisplayMode\"),this.request({method:\"ui/request-display-mode\",params:K},g,Q)}sendSizeChanged(K){return this.notification({method:\"ui/notifications/size-changed\",params:K})}setupSizeChangedNotifications(){let K=!1,Q=0,X=0,Y=()=>{if(K)return;K=!0,requestAnimationFrame(()=>{K=!1;let $=document.documentElement,G=$.style.height;$.style.height=\"max-content\";let j=Math.ceil($.getBoundingClientRect().height);$.style.height=G;let W=Math.ceil(window.innerWidth);if(W!==Q||j!==X)Q=W,X=j,this.sendSizeChanged({width:W,height:j})})};Y();let Z=new ResizeObserver(Y);return Z.observe(document.documentElement),Z.observe(document.body),()=>Z.disconnect()}async connect(K=new B(window.parent,window.parent),Q){if(this.transport)throw Error(\"App is already connected. Call close() before connecting again.\");this._initializedSent=!1,await super.connect(K);try{let X=await this.request({method:\"ui/initialize\",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:w}},u,Q);if(X===void 0)throw Error(`Server sent invalid initialize result: ${X}`);if(this._hostCapabilities=X.hostCapabilities,this._hostInfo=X.hostInfo,this._hostContext=X.hostContext,await this.notification({method:\"ui/notifications/initialized\"}),this._initializedSent=!0,this.options?.autoResize)this.setupSizeChangedNotifications()}catch(X){throw this.close(),X}}}function IQ({appInfo:K,capabilities:Q,onAppCreated:X,autoResize:Y=!0,strict:Z}){let[$,G]=c(null),[j,W]=c(!1),[L,_]=c(null);return sJ(()=>{let O=!0,N;async function e(){try{let q=new B(window.parent,window.parent);if(N=new R(K,Q,{autoResize:Y,strict:Z}),X?.(N),await N.connect(q),!O){N.close();return}G(N),W(!0),_(null)}catch(q){if(O)G(null),W(!1),_(q instanceof Error?q:Error(\"Failed to connect\"))}}return e(),()=>{O=!1,N?.close()}},[]),{app:$,isConnected:j,error:L}}import{useEffect as tJ}from\"react\";function wQ(K,Q){tJ(()=>{if(!K)return;return K.setupSizeChangedNotifications()},[K,Q])}import{useEffect as eJ,useState as JK}from\"react\";function kQ(){let[K,Q]=JK(F);return eJ(()=>{let X=new MutationObserver(()=>{Q(F())});return X.observe(document.documentElement,{attributes:!0,attributeFilter:[\"data-theme\",\"class\"],characterData:!1,childList:!1,subtree:!1}),()=>X.disconnect()},[]),K}import{useEffect as M,useRef as t}from\"react\";function KK(K,Q){let X=t(!1);M(()=>{if(X.current)return;if(Q?.theme)E(Q.theme);if(Q?.styles?.variables)I(Q.styles.variables);if(Q?.theme||Q?.styles?.variables)X.current=!0},[Q]),M(()=>{if(!K)return;let Y=(Z)=>{if(Z.theme)E(Z.theme);if(Z.styles?.variables)I(Z.styles.variables)};return K.addEventListener(\"hostcontextchanged\",Y),()=>K.removeEventListener(\"hostcontextchanged\",Y)},[K])}function QK(K,Q){let X=t(!1);M(()=>{if(X.current)return;if(Q?.styles?.css?.fonts)U(Q.styles.css.fonts),X.current=!0},[Q]),M(()=>{if(!K)return;let Y=(Z)=>{if(Z.styles?.css?.fonts)U(Z.styles.css.fonts)};return K.addEventListener(\"hostcontextchanged\",Y),()=>K.removeEventListener(\"hostcontextchanged\",Y)},[K])}function xQ(K,Q){KK(K,Q),QK(K,Q)}export{xQ as useHostStyles,KK as useHostStyleVariables,QK as useHostFonts,kQ as useDocumentTheme,wQ as useAutoResize,IQ as useApp,F as getDocumentTheme,I as applyHostStyleVariables,U as applyHostFonts,E as applyDocumentTheme,WJ as TOOL_RESULT_METHOD,H as TOOL_INPUT_PARTIAL_METHOD,jJ as TOOL_INPUT_METHOD,LJ as TOOL_CANCELLED_METHOD,GJ as SIZE_CHANGED_METHOD,$J as SANDBOX_RESOURCE_READY_METHOD,ZJ as SANDBOX_PROXY_READY_METHOD,NQ as RESOURCE_URI_META_KEY,VJ as RESOURCE_TEARDOWN_METHOD,BQ as RESOURCE_MIME_TYPE,BJ as REQUEST_TEARDOWN_METHOD,qJ as REQUEST_DISPLAY_MODE_METHOD,z as ProtocolWithEvents,B as PostMessageTransport,QJ as OPEN_LINK_METHOD,yJ as McpUiUpdateModelContextRequestSchema,s as McpUiToolVisibilitySchema,y as McpUiToolResultNotificationSchema,bJ as McpUiToolMetaSchema,b as McpUiToolInputPartialNotificationSchema,S as McpUiToolInputNotificationSchema,x as McpUiToolCancelledNotificationSchema,i as McpUiThemeSchema,T as McpUiSupportedContentBlockModalitiesSchema,HJ as McpUiSizeChangedNotificationSchema,gJ as McpUiSandboxResourceReadyNotificationSchema,wJ as McpUiSandboxProxyReadyNotificationSchema,TJ as McpUiResourceTeardownResultSchema,v as McpUiResourceTeardownRequestSchema,D as McpUiResourcePermissionsSchema,CJ as McpUiResourceMetaSchema,P as McpUiResourceCspSchema,AJ as McpUiRequestTeardownNotificationSchema,g as McpUiRequestDisplayModeResultSchema,SJ as McpUiRequestDisplayModeRequestSchema,A as McpUiOpenLinkResultSchema,zJ as McpUiOpenLinkRequestSchema,C as McpUiMessageResultSchema,vJ as McpUiMessageRequestSchema,kJ as McpUiInitializedNotificationSchema,u as McpUiInitializeResultSchema,fJ as McpUiInitializeRequestSchema,n as McpUiHostStylesSchema,p as McpUiHostCssSchema,f as McpUiHostContextSchema,d as McpUiHostContextChangedNotificationSchema,o as McpUiHostCapabilitiesSchema,k as McpUiDownloadFileResultSchema,xJ as McpUiDownloadFileRequestSchema,V as McpUiDisplayModeSchema,a as McpUiAppCapabilitiesSchema,YJ as MESSAGE_METHOD,w as LATEST_PROTOCOL_VERSION,_J as INITIALIZE_METHOD,OJ as INITIALIZED_METHOD,NJ as HOST_CONTEXT_CHANGED_METHOD,XJ as DOWNLOAD_FILE_METHOD,R as App};\n","import { useCallback, useSyncExternalStore } from 'react';\nimport type { App, McpUiHostContext, McpUiStyles } from '@modelcontextprotocol/ext-apps';\nimport {\n applyDocumentTheme,\n applyHostStyleVariables,\n applyHostFonts,\n} from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\nimport { DEFAULT_STYLE_VARIABLES } from '../lib/default-style-variables';\n\n/**\n * Per-app subscriber registry.\n * The App class only supports a single onhostcontextchanged callback,\n * so we multiplex it to allow multiple hook instances to subscribe.\n *\n * Also applies `data-theme` and `color-scheme` to the document element\n * so that CSS selectors like `[data-theme=\"dark\"]` and Tailwind's `dark:`\n * variant work automatically.\n */\nconst registries = new WeakMap<App, Set<() => void>>();\n\n/**\n * Apply style variables to the document, falling back to defaults.\n * Host-provided variables override defaults since they're applied after.\n */\nfunction applyStyles(variables: McpUiStyles | undefined) {\n // Always apply defaults first so all CSS variables are defined\n applyHostStyleVariables(DEFAULT_STYLE_VARIABLES);\n // Override with host-provided values (if any)\n if (variables) {\n applyHostStyleVariables(variables);\n }\n}\n\nfunction getRegistry(app: App): Set<() => void> {\n let subs = registries.get(app);\n if (!subs) {\n subs = new Set();\n registries.set(app, subs);\n\n // Apply initial theme and style variables from the host context received during initialization\n const ctx = app.getHostContext();\n if (ctx?.theme) {\n applyDocumentTheme(ctx.theme);\n }\n applyStyles(ctx?.styles?.variables);\n if (ctx?.styles?.css?.fonts) {\n applyHostFonts(ctx.styles.css.fonts);\n }\n\n // Debounce timer for subscriber notifications.\n // Some hosts (e.g. ChatGPT) fire hostcontextchanged at hundreds of Hz while\n // the LLM is generating text, oscillating containerDimensions between two\n // values. Debouncing coalesces these rapid bursts into a single re-render\n // so SafeArea and other dimension-sensitive components don't flicker.\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n app.onhostcontextchanged = () => {\n // Read the full context from the app rather than relying on the\n // callback params, which may be a delta missing unchanged fields\n // like styles when only the theme toggled.\n const ctx = app.getHostContext();\n if (ctx?.theme) {\n applyDocumentTheme(ctx.theme);\n }\n applyStyles(ctx?.styles?.variables);\n if (ctx?.styles?.css?.fonts) {\n applyHostFonts(ctx.styles.css.fonts);\n }\n // Notify subscribers after a brief settling period.\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n for (const fn of subs!) fn();\n }, 50);\n };\n }\n return subs;\n}\n\n/**\n * Reactive access to the MCP Apps host context.\n * Subscribes to host context changes and re-renders when the context updates.\n *\n * @returns The current host context, or null if not connected.\n */\nexport function useHostContext(): McpUiHostContext | null {\n const app = useApp();\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (!app) return () => {};\n const subs = getRegistry(app);\n subs.add(onChange);\n return () => {\n subs.delete(onChange);\n };\n },\n [app]\n );\n\n const getSnapshot = useCallback(() => {\n return app?.getHostContext() ?? null;\n }, [app]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\nexport interface ToolData<TInput = unknown, TOutput = unknown> {\n input: TInput | null;\n inputPartial: TInput | null;\n output: TOutput | null;\n isError: boolean;\n isLoading: boolean;\n isCancelled: boolean;\n cancelReason: string | null;\n}\n\ninterface ToolDataStore<TInput, TOutput> {\n data: ToolData<TInput, TOutput>;\n listeners: Set<() => void>;\n}\n\nconst stores = new WeakMap<App, ToolDataStore<unknown, unknown>>();\n\nfunction getStore<TInput, TOutput>(\n app: App,\n defaultInput?: TInput,\n defaultOutput?: TOutput\n): ToolDataStore<TInput, TOutput> {\n let store = stores.get(app) as ToolDataStore<TInput, TOutput> | undefined;\n if (!store) {\n store = {\n data: {\n input: defaultInput ?? null,\n inputPartial: null,\n output: defaultOutput ?? null,\n isError: false,\n isLoading: !defaultOutput,\n isCancelled: false,\n cancelReason: null,\n },\n listeners: new Set(),\n };\n stores.set(app, store as ToolDataStore<unknown, unknown>);\n\n const notify = () => {\n for (const fn of store!.listeners) fn();\n };\n\n app.ontoolinput = (_params) => {\n store!.data = {\n ...store!.data,\n input: _params.arguments as TInput,\n inputPartial: null,\n };\n notify();\n };\n\n app.ontoolinputpartial = (_params) => {\n store!.data = {\n ...store!.data,\n inputPartial: _params.arguments as TInput,\n };\n notify();\n };\n\n app.ontoolresult = (_params) => {\n store!.data = {\n ...store!.data,\n output: (_params.structuredContent ?? _params.content) as TOutput,\n isError: _params.isError ?? false,\n isLoading: false,\n };\n notify();\n };\n\n app.ontoolcancelled = (_params) => {\n store!.data = {\n ...store!.data,\n isCancelled: true,\n cancelReason: _params.reason ?? null,\n isLoading: false,\n };\n notify();\n };\n }\n return store;\n}\n\n/**\n * Reactive access to tool input and output data from the MCP Apps host.\n *\n * @param defaultInput - Optional default input value before host sends data.\n * @param defaultOutput - Optional default output value before host sends data.\n */\nexport function useToolData<TInput = unknown, TOutput = unknown>(\n defaultInput?: TInput,\n defaultOutput?: TOutput\n): ToolData<TInput, TOutput> {\n const app = useApp();\n const defaultInputRef = useRef(defaultInput);\n const defaultOutputRef = useRef(defaultOutput);\n\n // Cache the null-app snapshot so getSnapshot returns a stable reference.\n // useSyncExternalStore compares with Object.is — a new object each call\n // would cause an infinite re-render loop.\n const nullSnapshot = useMemo<ToolData<TInput, TOutput>>(\n () => ({\n input: defaultInput ?? null,\n inputPartial: null,\n output: defaultOutput ?? null,\n isError: false,\n isLoading: !defaultOutput,\n isCancelled: false,\n cancelReason: null,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [] // Intentionally empty - only compute once on first render\n );\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (!app) return () => {};\n const store = getStore<TInput, TOutput>(\n app,\n defaultInputRef.current,\n defaultOutputRef.current\n );\n store.listeners.add(onChange);\n return () => {\n store.listeners.delete(onChange);\n };\n },\n [app]\n );\n\n const getSnapshot = useCallback((): ToolData<TInput, TOutput> => {\n if (!app) {\n return nullSnapshot;\n }\n return getStore<TInput, TOutput>(app, defaultInputRef.current, defaultOutputRef.current).data;\n }, [app, nullSnapshot]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type DeviceCapabilities = NonNullable<McpUiHostContext['deviceCapabilities']>;\n\nexport function useDeviceCapabilities(): DeviceCapabilities {\n const context = useHostContext();\n return context?.deviceCapabilities ?? {};\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiDisplayMode } from '@modelcontextprotocol/ext-apps';\n\nexport function useDisplayMode(): McpUiDisplayMode {\n const context = useHostContext();\n return context?.displayMode ?? 'inline';\n}\n","import { useHostContext } from './use-host-context';\n\nexport function useLocale(): string {\n const context = useHostContext();\n return context?.locale ?? 'en-US';\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type HostPlatform = NonNullable<McpUiHostContext['platform']>;\n\nexport function usePlatform(): HostPlatform | undefined {\n const context = useHostContext();\n return context?.platform;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\ntype SafeAreaInsets = NonNullable<McpUiHostContext['safeAreaInsets']>;\n\nconst DEFAULT_INSETS: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 };\n\nexport function useSafeArea(): SafeAreaInsets {\n const context = useHostContext();\n return context?.safeAreaInsets ?? DEFAULT_INSETS;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostStyles } from '@modelcontextprotocol/ext-apps';\n\nexport function useStyles(): McpUiHostStyles | undefined {\n const context = useHostContext();\n return context?.styles;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiTheme } from '@modelcontextprotocol/ext-apps';\n\nexport function useTheme(): McpUiTheme {\n const context = useHostContext();\n return context?.theme ?? 'light';\n}\n","import { useHostContext } from './use-host-context';\n\nconst LOCAL_TIME_ZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\nexport function useTimeZone(): string {\n const context = useHostContext();\n return context?.timeZone ?? LOCAL_TIME_ZONE;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\nexport type ToolInfo = NonNullable<McpUiHostContext['toolInfo']>;\n\nexport function useToolInfo(): ToolInfo | undefined {\n const context = useHostContext();\n return context?.toolInfo;\n}\n","import { useHostContext } from './use-host-context';\n\nexport function useUserAgent(): string | undefined {\n const context = useHostContext();\n return context?.userAgent;\n}\n","import { useHostContext } from './use-host-context';\nimport type { McpUiHostContext } from '@modelcontextprotocol/ext-apps';\n\ntype ContainerDimensions = NonNullable<McpUiHostContext['containerDimensions']>;\n\nexport type Viewport = ContainerDimensions & {\n maxHeight?: number;\n maxWidth?: number;\n height?: number;\n width?: number;\n};\n\nexport function useViewport(): Viewport | null {\n const context = useHostContext();\n return (context?.containerDimensions as Viewport | undefined) ?? null;\n}\n","import * as React from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n mql.addEventListener('change', onChange);\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n return !!isMobile;\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { useDisplayMode } from './use-display-mode';\nimport { useSafeArea } from './use-safe-area';\nimport { useViewport } from './use-viewport';\n\nexport interface SafeAreaProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n}\n\n/**\n * Wrapper component that applies safe-area padding and viewport constraints.\n *\n * Replaces the common boilerplate of calling `useSafeArea()` + `useViewport()`\n * and manually applying padding/maxHeight/maxWidth styles on a container div.\n *\n * In fullscreen mode, SafeArea fills the iframe viewport (`100dvh`) so that\n * flex column layouts (e.g. sticky header / scrollable content / sticky footer)\n * work correctly without each resource having to handle display mode sizing.\n *\n * @example\n * ```tsx\n * import { SafeArea } from 'sunpeak';\n *\n * export function MyResource() {\n * return (\n * <SafeArea className=\"h-full\">\n * <MyContent />\n * </SafeArea>\n * );\n * }\n * ```\n */\nexport const SafeArea = forwardRef<HTMLDivElement, SafeAreaProps>(function SafeArea(\n { children, style, ...props },\n ref\n) {\n const safeArea = useSafeArea();\n const viewport = useViewport();\n const displayMode = useDisplayMode();\n\n // In fullscreen, fill the iframe viewport so flex layouts work.\n // In inline/pip, do NOT apply containerDimensions.height as an explicit height.\n // Doing so creates a feedback loop: the host sends a small initial placeholder height,\n // SafeArea pins to it, the app fires sizechange with that small height, and the host\n // never corrects it. Instead, let content size naturally so sizechange reports the\n // real rendered height.\n const isFullscreen = displayMode === 'fullscreen';\n // Always use 100dvh in fullscreen — viewport.height may report content height\n // rather than the iframe viewport height, which would defeat overflow scrolling.\n const height = isFullscreen ? '100dvh' : undefined;\n\n return (\n <div\n ref={ref}\n style={{\n // Only set inline padding when safe-area insets are non-zero,\n // so CSS class padding (e.g. Tailwind `p-4`) can serve as defaults.\n paddingTop: safeArea.top || undefined,\n paddingBottom: safeArea.bottom || undefined,\n paddingLeft: safeArea.left || undefined,\n paddingRight: safeArea.right || undefined,\n height,\n // overflow:hidden ensures content doesn't escape the maxHeight boundary,\n // which also lets apps fill the space with their own scrollable container.\n maxHeight: viewport?.maxHeight,\n overflow: viewport?.maxHeight != null ? 'hidden' : undefined,\n width: viewport?.width,\n maxWidth: viewport?.maxWidth,\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n});\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for calling a server tool.\n */\nexport interface CallServerToolParams {\n /** Name of the tool to call */\n name: string;\n /** Arguments to pass to the tool */\n arguments?: Record<string, unknown>;\n}\n\n/**\n * Result from a server tool call.\n */\nexport interface CallServerToolResult {\n /** Content array from the tool response */\n content?: Array<{ type: string; text?: string; [key: string]: unknown }>;\n /** Structured data from the tool response */\n structuredContent?: Record<string, unknown>;\n /** Whether the tool call resulted in an error */\n isError?: boolean;\n}\n\n/**\n * Hook to call other MCP server tools from within an app.\n *\n * Returns a function that invokes a tool on the MCP server and returns its result.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const callServerTool = useCallServerTool();\n *\n * const handleRefresh = async () => {\n * const result = await callServerTool({\n * name: 'get_weather',\n * arguments: { city: 'Tokyo' }\n * });\n * console.log('Weather:', result?.content);\n * };\n *\n * return <button onClick={handleRefresh}>Refresh Weather</button>;\n * }\n * ```\n */\nexport function useCallServerTool(): (\n params: CallServerToolParams\n) => Promise<CallServerToolResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: CallServerToolParams) => {\n if (!app) {\n console.warn('[useCallServerTool] App not connected');\n return undefined;\n }\n return app.callServerTool(params as Parameters<App['callServerTool']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type {\n CreateMessageRequest,\n CreateMessageResult,\n CreateMessageResultWithTools,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport type CreateSamplingMessageParams = CreateMessageRequest['params'];\nexport type { CreateMessageResult, CreateMessageResultWithTools };\n\nexport function useCreateSamplingMessage(): (\n params: CreateSamplingMessageParams\n) => Promise<CreateMessageResult | CreateMessageResultWithTools | undefined> {\n const app = useApp();\n return useCallback(\n async (params: CreateSamplingMessageParams) => {\n if (!app) {\n console.warn('[useCreateSamplingMessage] App not connected');\n return undefined;\n }\n return app.createSamplingMessage(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { McpUiDownloadFileRequest } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for downloading a file through the host.\n */\nexport type DownloadFileParams = McpUiDownloadFileRequest['params'];\n\n/**\n * Result from a file download request.\n */\nexport interface DownloadFileResult {\n /** Whether the download failed (e.g. user cancelled or host denied). */\n isError?: boolean;\n}\n\n/**\n * Hook to download files through the host.\n *\n * Since MCP Apps run in sandboxed iframes where direct downloads are blocked,\n * this provides a host-mediated mechanism for file exports. Supports embedded\n * text/binary content and resource links.\n *\n * @example\n * ```tsx\n * function ExportButton({ data }: { data: unknown }) {\n * const downloadFile = useDownloadFile();\n *\n * const handleExport = async () => {\n * await downloadFile({\n * contents: [{\n * type: 'resource',\n * resource: {\n * uri: 'file:///export.json',\n * mimeType: 'application/json',\n * text: JSON.stringify(data, null, 2),\n * },\n * }],\n * });\n * };\n *\n * return <button onClick={handleExport}>Export JSON</button>;\n * }\n * ```\n */\nexport function useDownloadFile(): (\n params: DownloadFileParams\n) => Promise<DownloadFileResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: DownloadFileParams) => {\n if (!app) {\n console.warn('[useDownloadFile] App not connected');\n return undefined;\n }\n return app.downloadFile(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for listing server resources.\n */\nexport interface ListServerResourcesParams {\n /** Pagination cursor from a previous response. */\n cursor?: string;\n}\n\n/**\n * A resource available on the MCP server.\n */\nexport interface ServerResource {\n /** Resource URI. */\n uri: string;\n /** Human-readable name. */\n name: string;\n /** Optional description. */\n description?: string;\n /** MIME type hint. */\n mimeType?: string;\n}\n\n/**\n * Result from listing server resources.\n */\nexport interface ListServerResourcesResult {\n /** Available resources. */\n resources: ServerResource[];\n /** Cursor for fetching the next page, if more results exist. */\n nextCursor?: string;\n}\n\n/**\n * Hook to discover available resources on the originating MCP server.\n *\n * Resources are proxied through the host. Supports pagination via cursor.\n * Use {@link useReadServerResource} to read a discovered resource.\n *\n * @example\n * ```tsx\n * function ResourcePicker() {\n * const listServerResources = useListServerResources();\n * const [resources, setResources] = useState<ServerResource[]>([]);\n *\n * useEffect(() => {\n * listServerResources().then(result => {\n * if (result) setResources(result.resources);\n * });\n * }, [listServerResources]);\n *\n * return (\n * <ul>\n * {resources.map(r => <li key={r.uri}>{r.name}</li>)}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useListServerResources(): (\n params?: ListServerResourcesParams\n) => Promise<ListServerResourcesResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params?: ListServerResourcesParams) => {\n if (!app) {\n console.warn('[useListServerResources] App not connected');\n return undefined;\n }\n return app.listServerResources(params as Parameters<App['listServerResources']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for opening a link.\n */\nexport interface OpenLinkParams {\n /** URL to open */\n url: string;\n}\n\n/**\n * Hook to open external links through the host.\n *\n * Opens a URL in a new tab/window through the host's link handling mechanism.\n * This is preferred over `window.open()` as it respects the host's security policies.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const openLink = useOpenLink();\n *\n * return (\n * <button onClick={() => openLink({ url: 'https://example.com' })}>\n * Visit Website\n * </button>\n * );\n * }\n * ```\n */\nexport function useOpenLink(): (params: OpenLinkParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: OpenLinkParams) => {\n if (!app) {\n console.warn('[useOpenLink] App not connected');\n return;\n }\n await app.openLink(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Parameters for reading a server resource.\n */\nexport interface ReadServerResourceParams {\n /** URI of the resource to read (e.g. `file:///path` or custom scheme). */\n uri: string;\n}\n\n/**\n * Result from reading a server resource.\n */\nexport interface ReadServerResourceResult {\n /** Resource contents returned by the server. */\n contents: Array<{ uri: string; mimeType?: string; text?: string; blob?: string }>;\n}\n\n/**\n * Hook to read resources from the originating MCP server.\n *\n * Resources are proxied through the host. Use {@link useListServerResources}\n * to discover available resources first.\n *\n * @example\n * ```tsx\n * function VideoPlayer() {\n * const readServerResource = useReadServerResource();\n * const [src, setSrc] = useState<string>();\n *\n * const loadVideo = async (uri: string) => {\n * const result = await readServerResource({ uri });\n * const content = result?.contents[0];\n * if (content && 'blob' in content && content.blob) {\n * const binary = atob(content.blob);\n * const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));\n * const blob = new Blob([bytes], { type: content.mimeType });\n * setSrc(URL.createObjectURL(blob));\n * }\n * };\n *\n * return src ? <video src={src} controls /> : <button onClick={() => loadVideo('videos://intro')}>Load</button>;\n * }\n * ```\n */\nexport function useReadServerResource(): (\n params: ReadServerResourceParams\n) => Promise<ReadServerResourceResult | undefined> {\n const app = useApp();\n return useCallback(\n async (params: ReadServerResourceParams) => {\n if (!app) {\n console.warn('[useReadServerResource] App not connected');\n return undefined;\n }\n return app.readServerResource(params as Parameters<App['readServerResource']>[0]);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport type {\n RegisteredAppTool,\n AppToolCallback,\n StandardSchemaV1,\n} from '@modelcontextprotocol/ext-apps';\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport interface RegisterToolConfig {\n title?: string;\n description?: string;\n inputSchema?: StandardSchemaV1;\n outputSchema?: StandardSchemaV1;\n annotations?: ToolAnnotations;\n _meta?: Record<string, unknown>;\n}\n\nexport function useRegisterTool(): (\n name: string,\n config: RegisterToolConfig,\n cb: AppToolCallback<StandardSchemaV1 | undefined, StandardSchemaV1 | undefined>\n) => RegisteredAppTool | undefined {\n const app = useApp();\n return useCallback(\n (\n name: string,\n config: RegisterToolConfig,\n cb: AppToolCallback<StandardSchemaV1 | undefined, StandardSchemaV1 | undefined>\n ) => {\n if (!app) {\n console.warn('[useRegisterTool] App not connected');\n return undefined;\n }\n return app.registerTool(name, config, cb);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\nimport { useHostContext } from './use-host-context';\n\n/**\n * Display modes available for apps.\n */\nexport type AppDisplayMode = 'inline' | 'pip' | 'fullscreen';\n\n/**\n * Hook to request a display mode change.\n *\n * Returns a function to request display mode changes and the list of available modes.\n * Always check `availableModes` before requesting a mode change.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const { requestDisplayMode, availableModes } = useRequestDisplayMode();\n *\n * return (\n * <>\n * {availableModes?.includes('fullscreen') && (\n * <button onClick={() => requestDisplayMode('fullscreen')}>\n * Fullscreen\n * </button>\n * )}\n * {availableModes?.includes('pip') && (\n * <button onClick={() => requestDisplayMode('pip')}>\n * Picture-in-Picture\n * </button>\n * )}\n * </>\n * );\n * }\n * ```\n */\nexport function useRequestDisplayMode(): {\n /** Request a display mode change */\n requestDisplayMode: (mode: AppDisplayMode) => Promise<void>;\n /** List of display modes the host supports */\n availableModes: AppDisplayMode[] | undefined;\n} {\n const app = useApp();\n const hostContext = useHostContext();\n\n const requestDisplayMode = useCallback(\n async (mode: AppDisplayMode) => {\n if (!app) {\n console.warn('[useRequestDisplayMode] App not connected');\n return;\n }\n await app.requestDisplayMode({ mode });\n },\n [app]\n );\n\n return {\n requestDisplayMode,\n availableModes: hostContext?.availableDisplayModes as AppDisplayMode[] | undefined,\n };\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Hook to request the host to tear down this app.\n *\n * Sends a notification to the host requesting that it initiate teardown.\n * If the host approves, it will send the standard teardown request back\n * to the app (triggering any `useTeardown` callbacks) before unmounting.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const requestTeardown = useRequestTeardown();\n *\n * return (\n * <button onClick={() => requestTeardown()}>\n * Close App\n * </button>\n * );\n * }\n * ```\n */\nexport function useRequestTeardown(): () => Promise<void> {\n const app = useApp();\n return useCallback(async () => {\n if (!app) {\n console.warn('[useRequestTeardown] App not connected');\n return;\n }\n await app.requestTeardown();\n }, [app]);\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Log levels for structured logging.\n */\nexport type LogLevel = 'debug' | 'info' | 'warning' | 'error' | 'critical';\n\n/**\n * Parameters for sending a log message.\n */\nexport interface SendLogParams {\n /** Log level */\n level: LogLevel;\n /** Log data (string or object) */\n data: unknown;\n /** Optional logger name for categorization */\n logger?: string;\n}\n\n/**\n * Hook to send structured log messages to the host.\n *\n * Sends logs through the MCP protocol rather than just console.log.\n * Useful for debugging in production where console isn't accessible.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const sendLog = useSendLog();\n *\n * const handleAction = () => {\n * sendLog({ level: 'info', data: 'User clicked button' });\n * sendLog({\n * level: 'debug',\n * data: { action: 'click', target: 'submit' },\n * logger: 'analytics'\n * });\n * };\n *\n * return <button onClick={handleAction}>Click Me</button>;\n * }\n * ```\n */\nexport function useSendLog(): (params: SendLogParams) => void {\n const app = useApp();\n return useCallback(\n (params: SendLogParams) => {\n if (!app) {\n // Fall back to console when not connected\n const consoleFn =\n params.level === 'error' || params.level === 'critical'\n ? console.error\n : params.level === 'warning'\n ? console.warn\n : params.level === 'debug'\n ? console.debug\n : console.log;\n consoleFn(`[${params.logger ?? 'app'}]`, params.data);\n return;\n }\n app.sendLog(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * Content item for a message.\n */\nexport interface MessageContent {\n type: 'text';\n text: string;\n}\n\n/**\n * Parameters for sending a message.\n */\nexport interface SendMessageParams {\n /** Role must be 'user' for MCP Apps */\n role: 'user';\n /** Content array for the message */\n content: MessageContent[];\n}\n\n/**\n * Hook to send follow-up messages to the conversation.\n *\n * Sends a message that appears in the conversation as if the user sent it.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const sendMessage = useSendMessage();\n *\n * const handleSubmit = async () => {\n * await sendMessage({\n * role: 'user',\n * content: [{ type: 'text', text: 'Please update the chart' }]\n * });\n * };\n *\n * return <button onClick={handleSubmit}>Request Update</button>;\n * }\n * ```\n */\nexport function useSendMessage(): (params: SendMessageParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: SendMessageParams) => {\n if (!app) {\n console.warn('[useSendMessage] App not connected');\n return;\n }\n await app.sendMessage(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from './use-app';\n\nexport function useSendToolListChanged(): () => Promise<void> {\n const app = useApp();\n return useCallback(async () => {\n if (!app) {\n console.warn('[useSendToolListChanged] App not connected');\n return;\n }\n await app.sendToolListChanged();\n }, [app]);\n}\n","import { useCallback } from 'react';\nimport type { McpUiUpdateModelContextRequest } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/** Parameters for updating model context — matches the MCP Apps SDK type. */\nexport type UpdateModelContextParams = McpUiUpdateModelContextRequest['params'];\n\n/**\n * Send model context updates to the host.\n *\n * Unlike `useAppState` (which automatically syncs structured state),\n * this hook gives direct control over when and what is sent to the\n * model context — including text content blocks.\n *\n * Each call overwrites the previous context. The host includes the\n * last update in the model's next turn.\n *\n * @example\n * ```tsx\n * import { useUpdateModelContext } from 'sunpeak';\n *\n * function MyResource() {\n * const updateModelContext = useUpdateModelContext();\n *\n * const handleSelect = (item: Item) => {\n * updateModelContext({\n * structuredContent: { selectedItem: item },\n * });\n * };\n * }\n * ```\n */\nexport function useUpdateModelContext(): (params: UpdateModelContextParams) => Promise<void> {\n const app = useApp();\n\n return useCallback(\n async (params: UpdateModelContextParams) => {\n if (!app) return;\n await app.updateModelContext(params);\n },\n [app]\n );\n}\n","import { useApp } from './use-app';\n\n/**\n * Host version information.\n */\nexport interface HostVersion {\n /** Name of the host application */\n name: string;\n /** Version of the host application */\n version: string;\n}\n\n/**\n * Host capabilities indicating what features are supported.\n */\nexport interface HostCapabilities {\n /** Whether the host supports calling server tools */\n serverTools?: boolean;\n /** Whether the host supports opening external links */\n openLinks?: boolean;\n /** Whether the host supports structured logging */\n logging?: boolean;\n /** Whether the host supports sending messages */\n messages?: boolean;\n /** Whether the host supports display mode changes */\n displayModes?: boolean;\n /** Additional capability flags */\n [key: string]: unknown;\n}\n\n/**\n * Hook to get information about the host application.\n *\n * Returns the host's version and capabilities. Use capabilities to check\n * what features are available before using them.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const { hostVersion, hostCapabilities } = useHostInfo();\n *\n * return (\n * <div>\n * <p>Running in: {hostVersion?.name} v{hostVersion?.version}</p>\n * {hostCapabilities?.serverTools && (\n * <button>Call Server Tool</button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useHostInfo(): {\n /** Host application version info */\n hostVersion: HostVersion | undefined;\n /** Host capabilities */\n hostCapabilities: HostCapabilities | undefined;\n} {\n const app = useApp();\n return {\n hostVersion: app?.getHostVersion() as HostVersion | undefined,\n hostCapabilities: app?.getHostCapabilities() as HostCapabilities | undefined,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport type { App } from '@modelcontextprotocol/ext-apps';\nimport { useApp } from './use-app';\n\n/**\n * Per-app subscriber registry.\n * The App class only supports a single onteardown callback,\n * so we multiplex it to allow multiple hook instances to subscribe.\n */\nconst registries = new WeakMap<App, Set<() => Promise<void> | void>>();\n\nfunction getRegistry(app: App): Set<() => Promise<void> | void> {\n let subs = registries.get(app);\n if (!subs) {\n subs = new Set();\n registries.set(app, subs);\n\n app.onteardown = async () => {\n for (const fn of subs!) await fn();\n return {};\n };\n }\n return subs;\n}\n\n/**\n * Hook to register a cleanup callback before the app is unmounted.\n *\n * The callback runs when the host signals teardown, before the iframe is destroyed.\n * Use this for cleanup that must complete before unmount (e.g., saving state).\n * Multiple components can safely call this hook — all callbacks will run.\n *\n * @param callback - Async function to run on teardown.\n *\n * @example\n * ```tsx\n * function MyApp() {\n * const [data, setData] = useState({});\n *\n * useTeardown(async () => {\n * await saveToServer(data);\n * });\n *\n * return <Editor data={data} onChange={setData} />;\n * }\n * ```\n */\nexport function useTeardown(callback: () => Promise<void> | void): void {\n const app = useApp();\n const callbackRef = useRef(callback);\n\n // Keep callback ref up to date\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (!app) return;\n\n const subs = getRegistry(app);\n const wrapper = () => callbackRef.current();\n subs.add(wrapper);\n\n return () => {\n subs.delete(wrapper);\n };\n }, [app]);\n}\n","import { useEffect } from 'react';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { useApp } from './use-app';\n\nexport interface AppTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n}\n\nexport interface AppToolsConfig {\n /** Tools this app provides to the host */\n tools: AppTool[];\n /**\n * Handler called when the host invokes one of this app's tools.\n * Return a CallToolResult with the tool's output.\n */\n onCallTool: (params: {\n name: string;\n arguments?: Record<string, unknown>;\n }) => CallToolResult | Promise<CallToolResult>;\n}\n\n/**\n * Register tools that this app provides to the host.\n *\n * This enables bidirectional tool calling: the host can call tools\n * defined by the app, in addition to the app calling server tools.\n *\n * @example\n * ```tsx\n * import { useAppTools } from 'sunpeak';\n *\n * function MyResource() {\n * useAppTools({\n * tools: [\n * { name: 'get-selection', description: 'Get the current selection' },\n * ],\n * onCallTool: async ({ name, arguments: args }) => {\n * if (name === 'get-selection') {\n * return { content: [{ type: 'text', text: selectedText }] };\n * }\n * return { content: [], isError: true };\n * },\n * });\n * }\n * ```\n */\nexport function useAppTools(config: AppToolsConfig): void {\n const app = useApp();\n\n useEffect(() => {\n if (!app) return;\n\n // Advertise app-provided tools to the host. Full tool metadata (description,\n // schema) is registered server-side via registerAppTool; this provides\n // the runtime tool list to the host's listTools request.\n // eslint-disable-next-line react-hooks/immutability\n app.onlisttools = () => {\n return Promise.resolve({\n tools: config.tools.map((t) => ({\n name: t.name,\n ...(t.description ? { description: t.description } : {}),\n inputSchema: {\n type: 'object' as const,\n ...t.inputSchema,\n },\n })),\n });\n };\n\n app.oncalltool = (params) => {\n return Promise.resolve(config.onCallTool(params));\n };\n }, [app, config]);\n}\n","import { useCallback, useEffect, useRef, useState, type SetStateAction } from 'react';\nimport { useApp } from './use-app';\n\n/**\n * State management with automatic sync to host via updateModelContext.\n *\n * This hook provides React-like state management that automatically sends\n * state updates to the host via `app.updateModelContext()`. The host can\n * then include this state in the model's context for the next message.\n *\n * @example Basic usage\n * ```tsx\n * import { useAppState } from 'sunpeak';\n *\n * function MyResource() {\n * const [state, setState] = useAppState({ count: 0 });\n *\n * return (\n * <button onClick={() => setState(prev => ({ ...prev, count: prev.count + 1 }))}>\n * Count: {state.count}\n * </button>\n * );\n * }\n * ```\n *\n * @example With typed state\n * ```tsx\n * interface MyState {\n * selectedId: string | null;\n * items: string[];\n * }\n *\n * const [state, setState] = useAppState<MyState>({ selectedId: null, items: [] });\n * ```\n *\n * @param defaultState - Initial state value.\n * @returns A tuple of [state, setState] similar to React's useState.\n */\nexport function useAppState<T>(defaultState: T): readonly [T, (state: SetStateAction<T>) => void] {\n const app = useApp();\n const [state, _setState] = useState<T>(defaultState);\n const pendingSync = useRef<T | null>(null);\n\n // Listen for debug state injection from inspector (sunpeak/injectState message).\n // This is a debug feature that allows the inspector to inject state changes\n // without going through the normal MCP Apps protocol flow.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const handler = (event: MessageEvent) => {\n // Only accept messages from parent (inspector)\n if (event.source !== window.parent) return;\n\n const data = event.data;\n if (\n data &&\n typeof data === 'object' &&\n data.method === 'sunpeak/injectState' &&\n data.params?.state != null\n ) {\n _setState(data.params.state as T);\n }\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, []);\n\n // Flush pending state to host after render completes\n useEffect(() => {\n if (pendingSync.current != null && app) {\n const value = pendingSync.current;\n pendingSync.current = null;\n app\n .updateModelContext({\n structuredContent: value,\n })\n .catch(() => {\n // Silently ignore — host may not support updateModelContext\n });\n }\n });\n\n const setState = useCallback((action: SetStateAction<T>) => {\n _setState((prev) => {\n const next = typeof action === 'function' ? (action as (prev: T) => T)(prev) : action;\n pendingSync.current = next;\n return next;\n });\n }, []);\n\n return [state, setState] as const;\n}\n","function matchMediaQuery(query: string) {\n return window.matchMedia(query).matches;\n}\n\nfunction createMediaQueryFn(query: string) {\n return () => matchMediaQuery(query);\n}\n\nexport const prefersReducedMotion = createMediaQueryFn('(prefers-reduced-motion: reduce)');\n\nexport const isPrimarilyTouchDevice = createMediaQueryFn('(pointer: coarse)');\n\nexport const isHoverAvailable = createMediaQueryFn('(hover: hover)');\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Simulation } from '../types/simulation';
|
|
2
|
+
import { InspectorApp } from './app-types';
|
|
3
|
+
/**
|
|
4
|
+
* Flatten an `InspectorApp` to the `Record<string, Simulation>` shape the
|
|
5
|
+
* Inspector consumes internally. Returns an empty map if `app` is missing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function flattenAppToSimulations(app: InspectorApp | undefined): Record<string, Simulation>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { ServerToolMock } from '../types/simulation';
|
|
3
|
+
/** A resource owned by the App. The URI links it to one or more Tools. */
|
|
4
|
+
export interface InspectorAppResource {
|
|
5
|
+
/**
|
|
6
|
+
* URI that uniquely identifies this resource within the App. Tools refer
|
|
7
|
+
* to it via `tool._meta.openai.outputTemplate`. Typically `ui://...`.
|
|
8
|
+
*/
|
|
9
|
+
uri: string;
|
|
10
|
+
/**
|
|
11
|
+
* The HTML document for this resource. Pass the string returned by
|
|
12
|
+
* `mcpClient.readResource({ uri })`; the Inspector hands it to the
|
|
13
|
+
* sandbox iframe via PostMessage and never hosts it at a URL.
|
|
14
|
+
*/
|
|
15
|
+
html: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional MIME type. Defaults to `text/html`. The current Inspector only
|
|
18
|
+
* renders HTML — other types are reserved for future use.
|
|
19
|
+
*/
|
|
20
|
+
mimeType?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Optional MCP `_meta` payload carried through to the iframe. Used by the
|
|
23
|
+
* MCP Apps SDK for resource-declared sandbox permissions, CSP, etc.
|
|
24
|
+
*
|
|
25
|
+
* Type is intentionally loose (`Record<string, unknown>`) — the Inspector
|
|
26
|
+
* doesn't validate the shape, it only reads specific subkeys defensively
|
|
27
|
+
* (`_meta.ui.permissions`, `_meta.ui.prefersBorder`, `_meta.ui.csp`). The
|
|
28
|
+
* embedder is responsible for shape correctness if they want those
|
|
29
|
+
* features. Other fields are ignored.
|
|
30
|
+
*/
|
|
31
|
+
_meta?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
/** A simulation: one saved test state for a tool. */
|
|
34
|
+
export interface InspectorAppSimulation {
|
|
35
|
+
/**
|
|
36
|
+
* Unique simulation name within the tool — surfaced in the sidebar's
|
|
37
|
+
* Simulation picker.
|
|
38
|
+
*/
|
|
39
|
+
name: string;
|
|
40
|
+
/**
|
|
41
|
+
* Optional user prompt to display in the conversation chrome. When omitted,
|
|
42
|
+
* the Inspector shows a generic "Call my <tool> tool" message.
|
|
43
|
+
*/
|
|
44
|
+
userMessage?: string;
|
|
45
|
+
/** Tool arguments — sent to the resource via the MCP Apps protocol. */
|
|
46
|
+
toolInput?: Record<string, unknown>;
|
|
47
|
+
/** Pre-canned tool result — what the model would receive. */
|
|
48
|
+
toolResult?: CallToolResult;
|
|
49
|
+
/**
|
|
50
|
+
* Mock responses for `callServerTool` calls the resource makes back to the
|
|
51
|
+
* server. Same shape as the existing `ServerToolMock` API.
|
|
52
|
+
*/
|
|
53
|
+
serverTools?: Record<string, ServerToolMock>;
|
|
54
|
+
}
|
|
55
|
+
/** A tool defined by the App, plus any simulations testing its UI states. */
|
|
56
|
+
export interface InspectorAppTool {
|
|
57
|
+
/**
|
|
58
|
+
* MCP `Tool` definition. The tool's `_meta.openai.outputTemplate` selects
|
|
59
|
+
* which resource the Inspector renders when this tool runs.
|
|
60
|
+
*/
|
|
61
|
+
tool: Tool;
|
|
62
|
+
/** Optional saved test states for this tool. */
|
|
63
|
+
simulations?: InspectorAppSimulation[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One MCP App's data, in the shape the Inspector renders. Pass via the
|
|
67
|
+
* `app` prop on `<Inspector />` when embedding inside another React app.
|
|
68
|
+
*/
|
|
69
|
+
export interface InspectorApp {
|
|
70
|
+
/** Optional display name shown in the conversation chrome header. */
|
|
71
|
+
name?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Optional icon shown next to the name. Accepts either short text (e.g.
|
|
74
|
+
* an emoji like `🎵`) or an `https://` URL — the host shells render the
|
|
75
|
+
* URL as an `<img>` when it validates as an allowed origin, otherwise
|
|
76
|
+
* fall back to rendering the value as text.
|
|
77
|
+
*/
|
|
78
|
+
icon?: string;
|
|
79
|
+
/** Resources this App exposes — typically one entry per UI surface. */
|
|
80
|
+
resources: InspectorAppResource[];
|
|
81
|
+
/** Tools this App exposes — at least one per resource the user can reach. */
|
|
82
|
+
tools: InspectorAppTool[];
|
|
83
|
+
}
|