@mcp-apps-kit/ui
Advanced tools
+1
-1
@@ -1,2 +0,2 @@ | ||
| 'use strict';var extApps=require('@modelcontextprotocol/ext-apps');var y={debug:0,info:1,warn:2,error:3};function x(n,e){return y[n]>=y[e]}function C(){let n=new WeakSet;return (e,t)=>{if(typeof t=="object"&&t!==null){if(n.has(t))return "[Circular]";n.add(t);}return t}}function k(n){if(n==null||typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(n instanceof Error)return {name:n.name,message:n.message,stack:n.stack};try{return JSON.stringify(n),n}catch{try{let e=JSON.stringify(n,C());return JSON.parse(e)}catch{return "[Unserializable]"}}}function b(n){if(n===void 0)return "undefined";if(n===null)return "null";if(typeof n=="string")return n;if(n instanceof Error)return `${n.name}: ${n.message}`;try{return JSON.stringify(n,C())}catch{return "[Unstringifiable]"}}var f=class{constructor(e={}){this.adapter=null;this.buffer=[];this.flushTimer=null;this.isFlushing=false;this.mcpTransportFailed=false;this.config={enabled:e.enabled??false,level:e.level??"info",batchSize:e.batchSize??10,maxBufferSize:e.maxBufferSize??100,flushIntervalMs:e.flushIntervalMs??5e3,source:e.source??"mcp-apps-ui"};}setAdapter(e){this.adapter=e,this.mcpTransportFailed=false;}configure(e){e.enabled!==void 0&&(this.config.enabled=e.enabled),e.level!==void 0&&(this.config.level=e.level),e.batchSize!==void 0&&(this.config.batchSize=e.batchSize),e.maxBufferSize!==void 0&&(this.config.maxBufferSize=e.maxBufferSize),e.flushIntervalMs!==void 0&&(this.config.flushIntervalMs=e.flushIntervalMs,this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.scheduleFlush()),e.source!==void 0&&(this.config.source=e.source);}canUseMcpTransport(){return this.config.enabled&&!this.mcpTransportFailed&&this.adapter?.isConnected()===true}createEntry(e,t,o){return {level:e,message:t,data:o!==void 0?k(o):void 0,timestamp:new Date().toISOString(),source:this.config.source}}scheduleFlush(){this.flushTimer||this.buffer.length===0||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush();},this.config.flushIntervalMs));}async flush(){if(this.isFlushing||this.buffer.length===0)return;if(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),!this.canUseMcpTransport()){for(let t of this.buffer)this.outputToConsole(t);this.buffer=[];return}this.isFlushing=true;let e=[...this.buffer];this.buffer=[];try{this.adapter&&await this.adapter.callTool("log_debug",{entries:e});}catch{this.mcpTransportFailed||(this.mcpTransportFailed=true,console.info("[ClientDebugLogger] MCP log transport unavailable, using console fallback"));for(let t of e)this.outputToConsole(t);}finally{this.isFlushing=false,this.buffer.length>0&&this.scheduleFlush();}}outputToConsole(e){let t=`[${e.timestamp}] [${e.level.toUpperCase()}]`,o=e.data!==void 0?`${e.message} ${b(e.data)}`:e.message,s=`${t} ${o}`;try{switch(e.level){case "debug":console.debug(s);break;case "info":console.info(s);break;case "warn":console.warn(s);break;case "error":console.error(s);break}}catch{}}addToBuffer(e){if(this.buffer.length>=this.config.maxBufferSize){let t=this.buffer.shift();t&&this.outputToConsole(t);}if(this.buffer.push(e),e.level==="error"){this.flush();return}if(this.buffer.length>=this.config.batchSize){this.flush();return}this.scheduleFlush();}log(e,t,o){if(!x(e,this.config.level))return;let s=this.createEntry(e,t,o);if(!this.canUseMcpTransport()){this.outputToConsole(s);return}this.addToBuffer(s);}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}destroy(){if(this.buffer.length>0){for(let e of this.buffer)this.outputToConsole(e);this.buffer=[];}this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.adapter=null;}},h=new f;var d=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}async connect(){this.connected=true,console.log("[MockAdapter] Connected");}isConnected(){return this.connected}async callTool(e,t){console.log(`[MockAdapter] callTool("${e}",`,t,")");let o={_mock:true,tool:e,args:t,timestamp:Date.now()};return this.currentToolOutput=o,o}async sendMessage(e){console.log("[MockAdapter] sendMessage:",e);}async openLink(e){console.log(`[MockAdapter] openLink("${e}")`);}async requestDisplayMode(e){return console.log(`[MockAdapter] requestDisplayMode("${e}")`),this.context={...this.context,displayMode:e},this.notifyHostContextChange(),{mode:e}}requestClose(){console.log("[MockAdapter] requestClose()");}getState(){return this.state}setState(e){this.state=e,console.log("[MockAdapter] setState:",e);}async readResource(e){return console.log(`[MockAdapter] readResource("${e}")`),{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MockAdapter]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}emitToolResult(e){this.currentToolOutput=e;for(let t of this.toolResultHandlers)t(e);}emitToolInput(e){this.currentToolInput=e;for(let t of this.toolInputHandlers)t(e);}setHostContext(e){this.context={...this.context,...e},this.notifyHostContextChange();}emitContextChange(e){this.context=e,this.notifyHostContextChange();}setToolInput(e){this.currentToolInput=e;}emitToolCancelled(e){for(let t of this.toolCancelledHandlers)t(e);}emitTeardown(e){for(let t of this.teardownHandlers)t(e);}notifyHostContextChange(){for(let e of this.hostContextHandlers)e(this.context);}};var H={parse:n=>n},p=class{constructor(){this.connected=false;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"desktop"}}async connect(){if(this.connected)return;if(typeof window>"u"){this.connected=true;return}this.app=new extApps.App({name:"@mcp-apps-kit/ui",version:"0.0.0"},{}),this.app.onerror=t=>{this.log("error",t);},this.app.onhostcontextchanged=t=>{let o=t.hostContext??t;this.context=this.mapHostContext(o),this.currentToolMeta=this.extractToolMeta(o);for(let s of this.hostContextHandlers)s(this.context);},this.app.ontoolinput=t=>{let o=t.arguments;if(o){this.currentToolInput=o;for(let s of this.toolInputHandlers)s(o);}},this.app.ontoolresult=t=>{let o=this.extractToolOutput(t);this.currentToolOutput=o;for(let s of this.toolResultHandlers)s(o);},this.app.ontoolcancelled=t=>{let o=t.reason;for(let s of this.toolCancelledHandlers)s(o);},this.app.onteardown=async t=>{let o=t.reason;for(let s of this.teardownHandlers)s(o);return {}},await this.app.connect();let e=this.app.getHostContext();e&&(this.context=this.mapHostContext(e),this.currentToolMeta=this.extractToolMeta(e)),this.connected=true;}isConnected(){return this.connected}mapHostContext(e){let t=e??{},o=this.createDefaultContext(),s=t.theme==="dark"?"dark":t.theme==="light"?"light":o.theme,r=t.displayMode==="fullscreen"||t.displayMode==="pip"||t.displayMode==="inline"?t.displayMode:o.displayMode,i=Array.isArray(t.availableDisplayModes)?t.availableDisplayModes.filter(u=>typeof u=="string"):o.availableDisplayModes,g=(u=>u!==null&&typeof u=="object"&&!Array.isArray(u))(t.viewport)?{...o.viewport,...t.viewport}:o.viewport,l=typeof t.locale=="string"?t.locale:o.locale,v=typeof t.timeZone=="string"?t.timeZone:o.timeZone,T=o.platform;return {...o,theme:s,displayMode:r,availableDisplayModes:i,viewport:g,locale:l,timeZone:v,platform:T,userAgent:typeof t.userAgent=="string"?t.userAgent:o.userAgent,deviceCapabilities:t.deviceCapabilities,safeAreaInsets:t.safeAreaInsets,styles:t.styles,view:typeof t.view=="string"?t.view:o.view}}extractToolMeta(e){if(e===null||typeof e!="object")return;let t=e;if(!(!t.toolInfo||typeof t.toolInfo!="object"))return {toolInfo:t.toolInfo}}extractToolOutput(e){let t=e.structuredContent,o=e._meta,s=t&&typeof t=="object"&&!Array.isArray(t)?t:{};if(o&&typeof o=="object"&&!Array.isArray(o))return {...s,_meta:o};if(Object.keys(s).length===0){let r=e.content;if(Array.isArray(r)&&r.length>0){let i=r[0];if(i?.type==="text"&&typeof i.text=="string")try{let a=JSON.parse(i.text);if(a!==null&&typeof a=="object"&&!Array.isArray(a))return a}catch{}}}return s}async callTool(e,t){if(!this.app)throw new Error("MCP Apps adapter not connected");let o=await this.app.callServerTool({name:e,arguments:t});return this.extractToolOutput(o)}async sendMessage(e){if(!this.app)throw new Error("MCP Apps adapter not connected");if(e.type!=="text")throw new Error(`Unsupported message content type: ${e.type}`);await this.app.sendMessage({role:"user",content:[{type:"text",text:e.text}]});}async openLink(e){if(!this.app)throw new Error("MCP Apps adapter not connected");await this.app.openLink({url:e});}async requestDisplayMode(e){if(!this.app)throw new Error("MCP Apps adapter not connected");return await this.app.requestDisplayMode({mode:e})}requestClose(){}getState(){return null}setState(e){}async readResource(e){if(!this.app)throw new Error("MCP Apps adapter not connected");let o=await this.app.request.bind(this.app)({method:"resources/read",params:{uri:e}},H);return {contents:(Array.isArray(o.contents)?o.contents:[]).map(s=>{let r={uri:s.uri,mimeType:s.mimeType??"application/octet-stream"};if("text"in s&&typeof s.text=="string")return {...r,text:s.text};if("blob"in s&&typeof s.blob=="string"){let i=Uint8Array.from(atob(s.blob),a=>a.charCodeAt(0));return {...r,blob:i}}return r})}}log(e,t){if(this.app){let r={level:["debug","info","notice","warning","error","critical","alert","emergency"].includes(e)?e:"info",data:t,logger:"@mcp-apps-kit/ui"};try{this.app.sendLog(r);return}catch{}}({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MCP Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}};var c=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}readContextFromSDK(){let e=this.getOpenAI();if(!e)return;let t=typeof window<"u";if(typeof e.theme=="string"&&(this.context.theme=e.theme),typeof e.displayMode=="string"&&(this.context.displayMode=e.displayMode),typeof e.locale=="string"&&(this.context.locale=e.locale),typeof e.userAgent=="string"&&Object.assign(this.context,{userAgent:e.userAgent}),typeof e.view=="string"&&(this.context.view=e.view),e.safeArea&&typeof e.safeArea=="object"){let o=e.safeArea;this.context.safeAreaInsets={top:typeof o.top=="number"?o.top:0,right:typeof o.right=="number"?o.right:0,bottom:typeof o.bottom=="number"?o.bottom:0,left:typeof o.left=="number"?o.left:0};}typeof e.maxHeight=="number"&&(this.context.viewport={width:t?window.innerWidth:800,height:e.maxHeight}),console.log("[OpenAI Adapter] Read context from SDK:",this.context);}notifyContextChange(){console.log(`[OpenAI Adapter] Notifying ${String(this.hostContextHandlers.size)} context change handlers`);let e={...this.context};for(let t of this.hostContextHandlers)t(e);}getOpenAI(){return typeof window<"u"&&"openai"in window?window.openai:null}async connect(){await this.waitForOpenAI();let e=this.getOpenAI();e&&(console.log("[OpenAI Adapter] Available SDK methods:",Object.keys(e)),this.readContextFromSDK(),typeof e.getToolOutput=="function"?(this.currentToolOutput=e.getToolOutput(),console.log("[OpenAI Adapter] Got tool output from SDK")):e.toolOutput?(this.currentToolOutput=e.toolOutput,console.log("[OpenAI Adapter] Got tool output from SDK property")):e.result&&(this.currentToolOutput=e.result,console.log("[OpenAI Adapter] Got result from SDK")),typeof e.getToolInput=="function"?this.currentToolInput=e.getToolInput():e.toolInput?this.currentToolInput=e.toolInput:e.input&&(this.currentToolInput=e.input),typeof e.init=="function"&&await e.init()),this.setupGlobalsListener(),this.connected=true;}setupGlobalsListener(){typeof window>"u"||(this.globalsHandler=e=>{let t=e.data;(t==="openai:set_globals"||typeof t=="object"&&t!==null&&"type"in t&&t.type==="openai:set_globals"||typeof t=="object"&&t!==null&&"message"in t&&t.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals event, refreshing context"),setTimeout(()=>{let s=this.context.theme,r=this.context.locale,i=this.context.displayMode;this.readContextFromSDK(),(this.context.theme!==s||this.context.locale!==r||this.context.displayMode!==i)&&(console.log("[OpenAI Adapter] Context changed, notifying handlers"),this.notifyContextChange());},10));},window.addEventListener("message",this.globalsHandler));}async waitForOpenAI(e=5e3){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai already available");return}return console.log("[OpenAI Adapter] Waiting for window.openai..."),new Promise(t=>{let o=Date.now(),s=false,r=()=>{s||(s=true,window.removeEventListener("message",a),t());},i=()=>{if(!s){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai found via polling"),r();return}if(Date.now()-o>e){console.warn("[OpenAI Adapter] window.openai not found after timeout, proceeding anyway"),r();return}setTimeout(i,50);}},a=g=>{let l=g.data;(l==="openai:set_globals"||typeof l=="object"&&l!==null&&"type"in l&&l.type==="openai:set_globals"||typeof l=="object"&&l!==null&&"message"in l&&l.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals message"),setTimeout(()=>{this.getOpenAI()?(console.log("[OpenAI Adapter] window.openai available after set_globals"),r()):console.log("[OpenAI Adapter] window.openai still not available after set_globals, continuing poll");},50));};window.addEventListener("message",a),i();})}isConnected(){return this.connected}async callTool(e,t){let o=this.getOpenAI();if(o&&typeof o.callTool=="function")return o.callTool(e,t);throw new Error("OpenAI SDK not available")}async sendMessage(e){let t=this.getOpenAI();t&&typeof t.sendMessage=="function"&&await t.sendMessage(e);}async openLink(e){let t=this.getOpenAI();t&&typeof t.openLink=="function"?await t.openLink(e):window.open(e,"_blank");}async requestDisplayMode(e){let t=this.getOpenAI();if(t&&typeof t.requestDisplayMode=="function"){let o=await t.requestDisplayMode({mode:e});return this.context={...this.context,displayMode:o.mode},this.notifyContextChange(),o}return this.context={...this.context,displayMode:e},this.notifyContextChange(),{mode:e}}requestClose(){let e=this.getOpenAI();e&&typeof e.close=="function"&&e.close();}getState(){return this.state}setState(e){this.state=e;let t=this.getOpenAI();t&&typeof t.setState=="function"&&t.setState(e);}async uploadFile(e){let t=this.getOpenAI();if(t&&typeof t.uploadFile=="function")return t.uploadFile(e);throw new Error("File upload not supported")}async getFileDownloadUrl(e){let t=this.getOpenAI();if(t&&typeof t.getFileDownloadUrl=="function")return t.getFileDownloadUrl(e);throw new Error("File download not supported")}async readResource(e){let t=this.getOpenAI();return t&&typeof t.readResource=="function"?t.readResource(e):{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[ChatGPT Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),console.log(`[OpenAI Adapter] Host context handler added, total: ${String(this.hostContextHandlers.size)}`),()=>{this.hostContextHandlers.delete(e),console.log(`[OpenAI Adapter] Host context handler removed, total: ${String(this.hostContextHandlers.size)}`);}}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}};function S(){let n=window.location.href;if(n.includes("/api/apps/chatgpt/")||n.includes("chatgpt")||n.includes("sandbox-proxy")||n.includes("widget-content"))return true;let e=document.referrer;return !!(e.includes("chatgpt")||e.includes("openai.com"))}function w(){return typeof window>"u"?"mock":"openai"in window||S()?"openai":window.parent!==window?"mcp":"mock"}function m(n){return {async callTool(t,o){return await n.callTool(t,o)},async sendMessage(t){await n.sendMessage(t);},async sendFollowUpMessage(t){await n.sendMessage({type:"text",text:t});},async openLink(t){await n.openLink(t);},async requestDisplayMode(t){return n.requestDisplayMode(t)},requestClose(){n.requestClose();},getState(){return n.getState()},setState(t){n.setState(t);},...n.uploadFile&&{uploadFile:t=>{if(n.uploadFile)return n.uploadFile(t);throw new Error("uploadFile not supported")}},...n.getFileDownloadUrl&&{getFileDownloadUrl:t=>{if(n.getFileDownloadUrl)return n.getFileDownloadUrl(t);throw new Error("getFileDownloadUrl not supported")}},async readResource(t){return n.readResource(t)},log(t,o){n.log(t,o);},onToolResult(t){return n.onToolResult(t)},onToolInput(t){return n.onToolInput(t)},onToolCancelled(t){return n.onToolCancelled(t)},onHostContextChange(t){return n.onHostContextChange(t)},onTeardown(t){return n.onTeardown(t)},get hostContext(){return n.getHostContext()},get toolInput(){return n.getToolInput()},get toolOutput(){return n.getToolOutput()},get toolMeta(){return n.getToolMeta()}}}function I(n){switch(n){case "mcp":return new p;case "openai":return new c;case "mock":return new d;default:throw new Error(`Unknown adapter type: ${n}`)}}async function j(n){let e=n?.forceAdapter??w();if(!["mcp","openai","mock"].includes(e))throw new Error(`Unknown adapter type: ${e}`);let t=I(e);return await t.connect(),h.setAdapter(t),m(t)}exports.ClientDebugLogger=f;exports.McpAdapter=p;exports.MockAdapter=d;exports.OpenAIAdapter=c;exports.clientDebugLogger=h;exports.createAppsClient=m;exports.createClient=j;exports.detectProtocol=w;exports.safeSerialize=k;exports.safeStringify=b;exports.shouldLog=x;//# sourceMappingURL=index.cjs.map | ||
| 'use strict';var extApps=require('@modelcontextprotocol/ext-apps');var L="2025-11-05",D="text/html;profile=mcp-app",F="ui/resourceUri";function x(o){if(typeof document>"u")return;let e=o==="os"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":o;document.documentElement.classList.remove("light","dark"),document.documentElement.classList.add(e),document.documentElement.setAttribute("data-theme",e);}function H(){if(typeof document>"u")return "light";let o=document.documentElement.getAttribute("data-theme");return o==="dark"||o==="light"?o:document.documentElement.classList.contains("dark")?"dark":"light"}var w="mcp-apps-host-fonts";function k(o){if(typeof document>"u")return;let e=document.documentElement;for(let[t,n]of Object.entries(o)){let s=t.startsWith("--")?t:`--${t}`;e.style.setProperty(s,n);}}function b(o){if(typeof document>"u")return;let e=document.getElementById(w);e||(e=document.createElement("style"),e.id=w,document.head.appendChild(e)),e.textContent=o;}function A(){if(typeof document>"u")return;let o=document.getElementById(w);o&&o.remove();}function I(o){if(typeof document>"u")return;let e=document.documentElement;for(let t of Object.keys(o)){let n=t.startsWith("--")?t:`--${t}`;e.style.removeProperty(n);}}var u={CONNECTION_FAILED:"CONNECTION_FAILED",CONNECTION_TIMEOUT:"CONNECTION_TIMEOUT",NOT_CONNECTED:"NOT_CONNECTED",PROTOCOL_ERROR:"PROTOCOL_ERROR",UNSUPPORTED_OPERATION:"UNSUPPORTED_OPERATION",TOOL_CALL_FAILED:"TOOL_CALL_FAILED",TOOL_NOT_FOUND:"TOOL_NOT_FOUND",STATE_ERROR:"STATE_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR"},d=class extends Error{constructor(t,n,s,r){super(n);this.code=t;this.details=s;this.cause=r;this.name="UIError";}formatMessage(){let t=`[${this.code}] ${this.message}`;return this.details&&(t+=` ${JSON.stringify(this.details)}`),t}};var S={debug:0,info:1,warn:2,error:3};function O(o,e){return S[o]>=S[e]}function R(){let o=new WeakSet;return (e,t)=>{if(typeof t=="object"&&t!==null){if(o.has(t))return "[Circular]";o.add(t);}return t}}function M(o){if(o==null||typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o;if(o instanceof Error)return {name:o.name,message:o.message,stack:o.stack};try{return JSON.stringify(o),o}catch{try{let e=JSON.stringify(o,R());return JSON.parse(e)}catch{return "[Unserializable]"}}}function P(o){if(o===void 0)return "undefined";if(o===null)return "null";if(typeof o=="string")return o;if(o instanceof Error)return `${o.name}: ${o.message}`;try{return JSON.stringify(o,R())}catch{return "[Unstringifiable]"}}var h=class{constructor(e={}){this.adapter=null;this.buffer=[];this.flushTimer=null;this.isFlushing=false;this.mcpTransportFailed=false;this.config={enabled:e.enabled??false,level:e.level??"info",batchSize:e.batchSize??10,maxBufferSize:e.maxBufferSize??100,flushIntervalMs:e.flushIntervalMs??5e3,source:e.source??"mcp-apps-ui"};}setAdapter(e){this.adapter=e,this.mcpTransportFailed=false;}configure(e){e.enabled!==void 0&&(this.config.enabled=e.enabled),e.level!==void 0&&(this.config.level=e.level),e.batchSize!==void 0&&(this.config.batchSize=e.batchSize),e.maxBufferSize!==void 0&&(this.config.maxBufferSize=e.maxBufferSize),e.flushIntervalMs!==void 0&&(this.config.flushIntervalMs=e.flushIntervalMs,this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.scheduleFlush()),e.source!==void 0&&(this.config.source=e.source);}canUseMcpTransport(){return this.config.enabled&&!this.mcpTransportFailed&&this.adapter?.isConnected()===true}createEntry(e,t,n){return {level:e,message:t,data:n!==void 0?M(n):void 0,timestamp:new Date().toISOString(),source:this.config.source}}scheduleFlush(){this.flushTimer||this.buffer.length===0||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush();},this.config.flushIntervalMs));}async flush(){if(this.isFlushing||this.buffer.length===0)return;if(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),!this.canUseMcpTransport()){for(let t of this.buffer)this.outputToConsole(t);this.buffer=[];return}this.isFlushing=true;let e=[...this.buffer];this.buffer=[];try{this.adapter&&await this.adapter.callTool("log_debug",{entries:e});}catch{this.mcpTransportFailed||(this.mcpTransportFailed=true,console.info("[ClientDebugLogger] MCP log transport unavailable, using console fallback"));for(let t of e)this.outputToConsole(t);}finally{this.isFlushing=false,this.buffer.length>0&&this.scheduleFlush();}}outputToConsole(e){let t=`[${e.timestamp}] [${e.level.toUpperCase()}]`,n=e.data!==void 0?`${e.message} ${P(e.data)}`:e.message,s=`${t} ${n}`;try{switch(e.level){case "debug":console.debug(s);break;case "info":console.info(s);break;case "warn":console.warn(s);break;case "error":console.error(s);break}}catch{}}addToBuffer(e){if(this.buffer.length>=this.config.maxBufferSize){let t=this.buffer.shift();t&&this.outputToConsole(t);}if(this.buffer.push(e),e.level==="error"){this.flush();return}if(this.buffer.length>=this.config.batchSize){this.flush();return}this.scheduleFlush();}log(e,t,n){if(!O(e,this.config.level))return;let s=this.createEntry(e,t,n);if(!this.canUseMcpTransport()){this.outputToConsole(s);return}this.addToBuffer(s);}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}destroy(){if(this.buffer.length>0){for(let e of this.buffer)this.outputToConsole(e);this.buffer=[];}this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.adapter=null;}},v=new h;var c=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolInputPartialHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.mockHostCapabilities={logging:{},openLinks:{},theming:{themes:["light","dark","os"]},displayModes:{modes:["inline","fullscreen","pip","panel"]},statePersistence:{persistent:true},serverTools:{listChanged:false},serverResources:{listChanged:false},sizeNotifications:{},partialToolInput:{},appTools:{listChanged:false},fileUpload:{},safeAreaInsets:{},views:{}};this.mockHostVersion={name:"MockHost",version:"1.0.0"};this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}async connect(){this.connected=true,console.log("[MockAdapter] Connected");}isConnected(){return this.connected}async callTool(e,t){console.log(`[MockAdapter] callTool("${e}",`,t,")");let n={_mock:true,tool:e,args:t,timestamp:Date.now()};return this.currentToolOutput=n,n}async sendMessage(e){console.log("[MockAdapter] sendMessage:",e);}async openLink(e){console.log(`[MockAdapter] openLink("${e}")`);}async requestDisplayMode(e){return console.log(`[MockAdapter] requestDisplayMode("${e}")`),this.context={...this.context,displayMode:e},this.notifyHostContextChange(),{mode:e}}requestClose(){console.log("[MockAdapter] requestClose()");}getState(){return this.state}setState(e){this.state=e,console.log("[MockAdapter] setState:",e);}async readResource(e){return console.log(`[MockAdapter] readResource("${e}")`),{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MockAdapter]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}emitToolResult(e){this.currentToolOutput=e;for(let t of this.toolResultHandlers)t(e);}emitToolInput(e){this.currentToolInput=e;for(let t of this.toolInputHandlers)t(e);}setHostContext(e){this.context={...this.context,...e},this.notifyHostContextChange();}emitContextChange(e){this.context=e,this.notifyHostContextChange();}setToolInput(e){this.currentToolInput=e;}emitToolCancelled(e){for(let t of this.toolCancelledHandlers)t(e);}emitTeardown(e){for(let t of this.teardownHandlers)t(e);}notifyHostContextChange(){for(let e of this.hostContextHandlers)e(this.context);}getHostCapabilities(){return this.mockHostCapabilities}getHostVersion(){return this.mockHostVersion}async sendLog(e,t){console.log(`[MockAdapter] sendLog(${e}):`,t);}async sendSizeChanged(e){console.log("[MockAdapter] sendSizeChanged:",e);}onToolInputPartial(e){return this.toolInputPartialHandlers.add(e),()=>this.toolInputPartialHandlers.delete(e)}setCallToolHandler(e){this.callToolHandler=e,console.log("[MockAdapter] setCallToolHandler: handler registered");}setListToolsHandler(e){this.listToolsHandler=e,console.log("[MockAdapter] setListToolsHandler: handler registered");}emitToolInputPartial(e){for(let t of this.toolInputPartialHandlers)t(e);}setMockHostCapabilities(e){this.mockHostCapabilities={...this.mockHostCapabilities,...e};}setMockHostVersion(e){this.mockHostVersion=e;}async simulateHostToolCall(e,t){if(!this.callToolHandler)throw new d(u.TOOL_NOT_FOUND,"No call tool handler registered");return this.callToolHandler(e,t)}async simulateHostListTools(){return this.listToolsHandler?this.listToolsHandler():{tools:[]}}};var N={parse:o=>o},g=class{constructor(){this.connected=false;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolInputPartialHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"desktop"}}async connect(){if(this.connected)return;if(typeof window>"u"){this.connected=true;return}this.app=new extApps.App({name:"@mcp-apps-kit/ui",version:"0.0.0"},{}),this.app.onerror=t=>{this.log("error",t);},this.app.onhostcontextchanged=t=>{let n=t.hostContext??t;this.context=this.mapHostContext(n),this.currentToolMeta=this.extractToolMeta(n);for(let s of this.hostContextHandlers)s(this.context);},this.app.ontoolinput=t=>{let n=t.arguments;if(n){this.currentToolInput=n;for(let s of this.toolInputHandlers)s(n);}},this.app.ontoolinputpartial=t=>{let n=t.arguments;if(n)for(let s of this.toolInputPartialHandlers)s(n);},this.app.oncalltool=async t=>{let{name:n,arguments:s}=t;try{if(this.callToolHandler){let r=await this.callToolHandler(n,s??{});return {content:[{type:"text",text:JSON.stringify(r)}]}}return {content:[{type:"text",text:`No handler registered for tool: ${n}`}],isError:!0}}catch(r){return {content:[{type:"text",text:r instanceof Error?r.message:String(r)}],isError:true}}},this.app.onlisttools=async()=>this.listToolsHandler?{tools:(await this.listToolsHandler()).map(n=>n.name)}:{tools:[]},this.app.ontoolresult=t=>{let n=this.extractToolOutput(t);this.currentToolOutput=n;for(let s of this.toolResultHandlers)s(n);},this.app.ontoolcancelled=t=>{let n=t.reason;for(let s of this.toolCancelledHandlers)s(n);},this.app.onteardown=async t=>{let n=t.reason;for(let s of this.teardownHandlers)s(n);return {}},await this.app.connect();let e=this.app.getHostContext();e&&(this.context=this.mapHostContext(e),this.currentToolMeta=this.extractToolMeta(e)),this.connected=true;}isConnected(){return this.connected}mapHostContext(e){let t=e??{},n=this.createDefaultContext(),s=t.theme==="dark"?"dark":t.theme==="light"?"light":n.theme,r=t.displayMode==="fullscreen"||t.displayMode==="pip"||t.displayMode==="inline"?t.displayMode:n.displayMode,i=Array.isArray(t.availableDisplayModes)?t.availableDisplayModes.filter(p=>typeof p=="string"):n.availableDisplayModes,m=(p=>p!==null&&typeof p=="object"&&!Array.isArray(p))(t.viewport)?{...n.viewport,...t.viewport}:n.viewport,l=typeof t.locale=="string"?t.locale:n.locale,T=typeof t.timeZone=="string"?t.timeZone:n.timeZone,E=n.platform;return {...n,theme:s,displayMode:r,availableDisplayModes:i,viewport:m,locale:l,timeZone:T,platform:E,userAgent:typeof t.userAgent=="string"?t.userAgent:n.userAgent,deviceCapabilities:t.deviceCapabilities,safeAreaInsets:t.safeAreaInsets,styles:t.styles,view:typeof t.view=="string"?t.view:n.view}}extractToolMeta(e){if(e===null||typeof e!="object")return;let t=e;if(!(!t.toolInfo||typeof t.toolInfo!="object"))return {toolInfo:t.toolInfo}}extractToolOutput(e){let t=e.structuredContent,n=e._meta,s=t&&typeof t=="object"&&!Array.isArray(t)?t:{};if(n&&typeof n=="object"&&!Array.isArray(n))return {...s,_meta:n};if(Object.keys(s).length===0){let r=e.content;if(Array.isArray(r)&&r.length>0){let i=r[0];if(i?.type==="text"&&typeof i.text=="string")try{let a=JSON.parse(i.text);if(a!==null&&typeof a=="object"&&!Array.isArray(a))return a}catch{}}}return s}async callTool(e,t){if(!this.app)throw new Error("MCP Apps adapter not connected");let n=await this.app.callServerTool({name:e,arguments:t});return this.extractToolOutput(n)}async sendMessage(e){if(!this.app)throw new Error("MCP Apps adapter not connected");if(e.type!=="text")throw new Error(`Unsupported message content type: ${e.type}`);await this.app.sendMessage({role:"user",content:[{type:"text",text:e.text}]});}async openLink(e){if(!this.app)throw new Error("MCP Apps adapter not connected");await this.app.openLink({url:e});}async requestDisplayMode(e){if(!this.app)throw new Error("MCP Apps adapter not connected");return await this.app.requestDisplayMode({mode:e})}requestClose(){}getState(){return null}setState(e){}async readResource(e){if(!this.app)throw new Error("MCP Apps adapter not connected");let n=await this.app.request.bind(this.app)({method:"resources/read",params:{uri:e}},N);return {contents:(Array.isArray(n.contents)?n.contents:[]).map(s=>{let r={uri:s.uri,mimeType:s.mimeType??"application/octet-stream"};if("text"in s&&typeof s.text=="string")return {...r,text:s.text};if("blob"in s&&typeof s.blob=="string"){let i=Uint8Array.from(atob(s.blob),a=>a.charCodeAt(0));return {...r,blob:i}}return r})}}log(e,t){if(this.app){let i={level:["debug","info","notice","warning","error","critical","alert","emergency"].includes(e)?e:"info",data:t,logger:"@mcp-apps-kit/ui"};try{this.app.sendLog(i);return}catch{}}({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MCP Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}getHostCapabilities(){if(!this.app)return;let e=this.app.getHostCapabilities();if(!e)return;let t=e,s=this.app.getHostContext()?.availableDisplayModes;return {logging:t.logging,openLinks:t.openLinks,serverResources:t.serverResources,serverTools:t.serverTools,experimental:t.experimental,theming:{themes:["light","dark"]},displayModes:s?{modes:s}:void 0,statePersistence:{persistent:false},sizeNotifications:{},partialToolInput:{},appTools:{listChanged:false}}}getHostVersion(){if(!this.app)return;let e=this.app.getHostVersion();if(e)return {name:e.name,version:e.version}}async sendLog(e,t){if(!this.app)throw new d(u.NOT_CONNECTED,"MCP Apps adapter not connected");await this.app.sendLog({level:e,data:t,logger:"@mcp-apps-kit/ui"});}async sendSizeChanged(e){if(!this.app)throw new d(u.NOT_CONNECTED,"MCP Apps adapter not connected");await this.app.sendSizeChanged({width:e.width,height:e.height});}onToolInputPartial(e){return this.toolInputPartialHandlers.add(e),()=>this.toolInputPartialHandlers.delete(e)}setCallToolHandler(e){this.callToolHandler=e;}setListToolsHandler(e){this.listToolsHandler=e;}};var f=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}readContextFromSDK(){let e=this.getOpenAI();if(!e)return;let t=typeof window<"u";if(typeof e.theme=="string"&&(this.context.theme=e.theme),typeof e.displayMode=="string"&&(this.context.displayMode=e.displayMode),typeof e.locale=="string"&&(this.context.locale=e.locale),typeof e.userAgent=="string"&&Object.assign(this.context,{userAgent:e.userAgent}),typeof e.view=="string"&&(this.context.view=e.view),e.safeArea&&typeof e.safeArea=="object"){let n=e.safeArea;this.context.safeAreaInsets={top:typeof n.top=="number"?n.top:0,right:typeof n.right=="number"?n.right:0,bottom:typeof n.bottom=="number"?n.bottom:0,left:typeof n.left=="number"?n.left:0};}typeof e.maxHeight=="number"&&(this.context.viewport={width:t?window.innerWidth:800,height:e.maxHeight}),console.log("[OpenAI Adapter] Read context from SDK:",this.context);}notifyContextChange(){console.log(`[OpenAI Adapter] Notifying ${String(this.hostContextHandlers.size)} context change handlers`);let e={...this.context};for(let t of this.hostContextHandlers)t(e);}getOpenAI(){return typeof window<"u"&&"openai"in window?window.openai:null}async connect(){await this.waitForOpenAI();let e=this.getOpenAI();e&&(console.log("[OpenAI Adapter] Available SDK methods:",Object.keys(e)),this.readContextFromSDK(),typeof e.getToolOutput=="function"?(this.currentToolOutput=e.getToolOutput(),console.log("[OpenAI Adapter] Got tool output from SDK")):e.toolOutput?(this.currentToolOutput=e.toolOutput,console.log("[OpenAI Adapter] Got tool output from SDK property")):e.result&&(this.currentToolOutput=e.result,console.log("[OpenAI Adapter] Got result from SDK")),typeof e.getToolInput=="function"?this.currentToolInput=e.getToolInput():e.toolInput?this.currentToolInput=e.toolInput:e.input&&(this.currentToolInput=e.input),typeof e.init=="function"&&await e.init()),this.setupGlobalsListener(),this.connected=true;}setupGlobalsListener(){typeof window>"u"||(this.globalsHandler=e=>{let t=e.data;(t==="openai:set_globals"||typeof t=="object"&&t!==null&&"type"in t&&t.type==="openai:set_globals"||typeof t=="object"&&t!==null&&"message"in t&&t.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals event, refreshing context"),setTimeout(()=>{let s=this.context.theme,r=this.context.locale,i=this.context.displayMode;this.readContextFromSDK(),(this.context.theme!==s||this.context.locale!==r||this.context.displayMode!==i)&&(console.log("[OpenAI Adapter] Context changed, notifying handlers"),this.notifyContextChange());},10));},window.addEventListener("message",this.globalsHandler));}async waitForOpenAI(e=5e3){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai already available");return}return console.log("[OpenAI Adapter] Waiting for window.openai..."),new Promise(t=>{let n=Date.now(),s=false,r=()=>{s||(s=true,window.removeEventListener("message",a),t());},i=()=>{if(!s){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai found via polling"),r();return}if(Date.now()-n>e){console.warn("[OpenAI Adapter] window.openai not found after timeout, proceeding anyway"),r();return}setTimeout(i,50);}},a=m=>{let l=m.data;(l==="openai:set_globals"||typeof l=="object"&&l!==null&&"type"in l&&l.type==="openai:set_globals"||typeof l=="object"&&l!==null&&"message"in l&&l.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals message"),setTimeout(()=>{this.getOpenAI()?(console.log("[OpenAI Adapter] window.openai available after set_globals"),r()):console.log("[OpenAI Adapter] window.openai still not available after set_globals, continuing poll");},50));};window.addEventListener("message",a),i();})}isConnected(){return this.connected}async callTool(e,t){let n=this.getOpenAI();if(n&&typeof n.callTool=="function")return n.callTool(e,t);throw new Error("OpenAI SDK not available")}async sendMessage(e){let t=this.getOpenAI();t&&typeof t.sendMessage=="function"&&await t.sendMessage(e);}async openLink(e){let t=this.getOpenAI();t&&typeof t.openLink=="function"?await t.openLink(e):window.open(e,"_blank");}async requestDisplayMode(e){let t=this.getOpenAI();if(t&&typeof t.requestDisplayMode=="function"){let n=await t.requestDisplayMode({mode:e});return this.context={...this.context,displayMode:n.mode},this.notifyContextChange(),n}return this.context={...this.context,displayMode:e},this.notifyContextChange(),{mode:e}}requestClose(){let e=this.getOpenAI();e&&typeof e.close=="function"&&e.close();}getState(){return this.state}setState(e){this.state=e;let t=this.getOpenAI();t&&typeof t.setState=="function"&&t.setState(e);}async uploadFile(e){let t=this.getOpenAI();if(t&&typeof t.uploadFile=="function")return t.uploadFile(e);throw new Error("File upload not supported")}async getFileDownloadUrl(e){let t=this.getOpenAI();if(t&&typeof t.getFileDownloadUrl=="function")return t.getFileDownloadUrl(e);throw new Error("File download not supported")}async readResource(e){let t=this.getOpenAI();return t&&typeof t.readResource=="function"?t.readResource(e):{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[ChatGPT Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),console.log(`[OpenAI Adapter] Host context handler added, total: ${String(this.hostContextHandlers.size)}`),()=>{this.hostContextHandlers.delete(e),console.log(`[OpenAI Adapter] Host context handler removed, total: ${String(this.hostContextHandlers.size)}`);}}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}getHostCapabilities(){let e=this.getOpenAI(),t=e&&typeof e.uploadFile=="function",n=this.context.safeAreaInsets!==void 0,s=this.context.view!==void 0;return {openLinks:{},logging:{},theming:{themes:["light","dark"]},displayModes:{modes:["inline","fullscreen","pip"]},statePersistence:{persistent:false},fileUpload:t?{}:void 0,safeAreaInsets:n?{}:void 0,views:s?{}:void 0}}getHostVersion(){}async sendLog(e,t){let n={debug:"debug",info:"info",notice:"info",warning:"warning",error:"error",critical:"error",alert:"error",emergency:"error"};this.log(n[e],t);}async sendSizeChanged(e){let t=this.getOpenAI();t&&typeof t.notifyIntrinsicHeight=="function"&&t.notifyIntrinsicHeight(e.height);}onToolInputPartial(e){return this.log("debug","onToolInputPartial is not supported on ChatGPT"),()=>{}}setCallToolHandler(e){this.log("debug","setCallToolHandler is not supported on ChatGPT");}setListToolsHandler(e){this.log("debug","setListToolsHandler is not supported on ChatGPT");}};function U(){let o=window.location.href;if(o.includes("/api/apps/chatgpt/")||o.includes("chatgpt")||o.includes("sandbox-proxy")||o.includes("widget-content"))return true;let e=document.referrer;return !!(e.includes("chatgpt")||e.includes("openai.com"))}function y(){return typeof window>"u"?"mock":"openai"in window||U()?"openai":window.parent!==window?"mcp":"mock"}function C(o){return {async callTool(t,n){return await o.callTool(t,n)},async sendMessage(t){await o.sendMessage(t);},async sendFollowUpMessage(t){await o.sendMessage({type:"text",text:t});},async openLink(t){await o.openLink(t);},async requestDisplayMode(t){return o.requestDisplayMode(t)},requestClose(){o.requestClose();},getState(){return o.getState()},setState(t){o.setState(t);},...o.uploadFile&&{uploadFile:t=>{if(o.uploadFile)return o.uploadFile(t);throw new Error("uploadFile not supported")}},...o.getFileDownloadUrl&&{getFileDownloadUrl:t=>{if(o.getFileDownloadUrl)return o.getFileDownloadUrl(t);throw new Error("getFileDownloadUrl not supported")}},async readResource(t){return o.readResource(t)},log(t,n){o.log(t,n);},onToolResult(t){return o.onToolResult(t)},onToolInput(t){return o.onToolInput(t)},onToolCancelled(t){return o.onToolCancelled(t)},onHostContextChange(t){return o.onHostContextChange(t)},onTeardown(t){return o.onTeardown(t)},onToolInputPartial(t){return o.onToolInputPartial(t)},getHostCapabilities(){return o.getHostCapabilities()},getHostVersion(){return o.getHostVersion()},async sendLog(t,n){return o.sendLog(t,n)},async sendSizeChanged(t){return o.sendSizeChanged(t)},setupSizeChangedNotifications(){if(typeof window>"u"||typeof ResizeObserver>"u")return ()=>{};let t=new ResizeObserver(n=>{for(let s of n){let{width:r,height:i}=s.contentRect;o.sendSizeChanged({width:Math.round(r),height:Math.round(i)});}});return t.observe(document.body),()=>{t.disconnect();}},setCallToolHandler(t){o.setCallToolHandler(t);},setListToolsHandler(t){o.setListToolsHandler(t);},get hostContext(){return o.getHostContext()},get toolInput(){return o.getToolInput()},get toolOutput(){return o.getToolOutput()},get toolMeta(){return o.getToolMeta()}}}function z(o){switch(o){case "mcp":return new g;case "openai":return new f;case "mock":return new c;default:throw new Error(`Unknown adapter type: ${o}`)}}async function de(o){let e=o?.forceAdapter??y();if(!["mcp","openai","mock"].includes(e))throw new Error(`Unknown adapter type: ${e}`);let t=z(e);return await t.connect(),v.setAdapter(t),C(t)}exports.ClientDebugLogger=h;exports.LATEST_PROTOCOL_VERSION=L;exports.McpAdapter=g;exports.MockAdapter=c;exports.OpenAIAdapter=f;exports.RESOURCE_MIME_TYPE=D;exports.RESOURCE_URI_META_KEY=F;exports.UIError=d;exports.UIErrorCode=u;exports.applyDocumentTheme=x;exports.applyHostFonts=b;exports.applyHostStyleVariables=k;exports.clearHostStyleVariables=I;exports.clientDebugLogger=v;exports.createAppsClient=C;exports.createClient=de;exports.detectProtocol=y;exports.getDocumentTheme=H;exports.removeHostFonts=A;exports.safeSerialize=M;exports.safeStringify=P;exports.shouldLog=O;//# sourceMappingURL=index.cjs.map | ||
| //# sourceMappingURL=index.cjs.map |
+438
-1
@@ -5,2 +5,119 @@ /** | ||
| /** | ||
| * Host capabilities advertised during handshake. | ||
| * Protocol-agnostic interface covering features from both MCP Apps and ChatGPT. | ||
| */ | ||
| interface HostCapabilities { | ||
| /** Host accepts log messages via sendLog() */ | ||
| logging?: Record<string, never>; | ||
| /** Host supports opening external URLs via openLink() */ | ||
| openLinks?: Record<string, never>; | ||
| /** Host supports theme switching (light/dark/os) */ | ||
| theming?: { | ||
| /** Supported themes */ | ||
| themes?: ("light" | "dark" | "os")[]; | ||
| }; | ||
| /** Host supports display mode changes */ | ||
| displayModes?: { | ||
| /** Available display modes */ | ||
| modes?: ("inline" | "fullscreen" | "pip" | "panel")[]; | ||
| }; | ||
| /** Host supports state persistence */ | ||
| statePersistence?: { | ||
| /** State is persisted across sessions */ | ||
| persistent?: boolean; | ||
| /** Maximum state size in bytes */ | ||
| maxSize?: number; | ||
| }; | ||
| /** Host can proxy resource reads to MCP server (MCP Apps only) */ | ||
| serverResources?: { | ||
| /** Host supports resources/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host can proxy tool calls to MCP server (MCP Apps only) */ | ||
| serverTools?: { | ||
| /** Host supports tools/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host supports size change notifications (MCP Apps only) */ | ||
| sizeNotifications?: Record<string, never>; | ||
| /** Host supports partial/streaming tool input (MCP Apps only) */ | ||
| partialToolInput?: Record<string, never>; | ||
| /** Host supports bidirectional tools - app can expose tools to host (MCP Apps only) */ | ||
| appTools?: { | ||
| /** Host supports tools/list_changed notifications from app */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host supports file uploads (ChatGPT only) */ | ||
| fileUpload?: { | ||
| /** Maximum file size in bytes */ | ||
| maxSize?: number; | ||
| /** Allowed MIME types */ | ||
| allowedTypes?: string[]; | ||
| }; | ||
| /** Host provides safe area insets (ChatGPT mobile) */ | ||
| safeAreaInsets?: Record<string, never>; | ||
| /** Host supports view identification (ChatGPT only) */ | ||
| views?: { | ||
| /** Supported view types */ | ||
| types?: string[]; | ||
| }; | ||
| /** Experimental features (structure TBD) */ | ||
| experimental?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Host version information returned after connection. | ||
| */ | ||
| interface HostVersion { | ||
| /** Host application name (e.g., "Claude Desktop") */ | ||
| name: string; | ||
| /** Host application version */ | ||
| version: string; | ||
| } | ||
| /** | ||
| * App capabilities declared during initialization. | ||
| * Tells the host what this app supports. | ||
| */ | ||
| interface AppCapabilities { | ||
| /** Experimental features (structure TBD) */ | ||
| experimental?: Record<string, unknown>; | ||
| /** App exposes MCP-style tools that the host can call */ | ||
| tools?: { | ||
| /** App supports tools/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| } | ||
| /** | ||
| * Parameters for size changed notifications. | ||
| */ | ||
| interface SizeChangedParams { | ||
| /** Widget width in pixels */ | ||
| width: number; | ||
| /** Widget height in pixels */ | ||
| height: number; | ||
| } | ||
| /** | ||
| * Tool definition for app-exposed tools (bidirectional support). | ||
| * Used when the app exposes tools that the host can call. | ||
| */ | ||
| interface AppToolDefinition { | ||
| /** Tool name */ | ||
| name: string; | ||
| /** Tool description */ | ||
| description?: string; | ||
| /** JSON Schema for input parameters */ | ||
| inputSchema?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Handler for tool calls from the host. | ||
| * @param toolName - Name of the tool being called | ||
| * @param args - Tool arguments | ||
| * @returns Tool result | ||
| */ | ||
| type CallToolHandler = (toolName: string, args: Record<string, unknown>) => Promise<unknown>; | ||
| /** | ||
| * Handler that returns the list of tools exposed by the app. | ||
| * @returns Array of tool definitions | ||
| */ | ||
| type ListToolsHandler = () => Promise<AppToolDefinition[]>; | ||
| /** | ||
| * Viewport dimensions | ||
@@ -260,2 +377,76 @@ */ | ||
| onTeardown(handler: (reason?: string) => void): () => void; | ||
| /** | ||
| * Subscribe to partial/streaming tool input | ||
| * | ||
| * Called when the host sends partial tool arguments during streaming. | ||
| * Useful for showing real-time input as the user types or as the model generates. | ||
| * | ||
| * @param handler - Callback for partial input | ||
| * @returns Unsubscribe function | ||
| */ | ||
| onToolInputPartial(handler: (input: Record<string, unknown>) => void): () => void; | ||
| /** | ||
| * Get host capabilities | ||
| * | ||
| * Returns the capabilities advertised by the host during handshake. | ||
| * Use this to check if features like logging or server tools are supported. | ||
| * | ||
| * @returns Host capabilities or undefined if not yet connected | ||
| */ | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| /** | ||
| * Get host version information | ||
| * | ||
| * Returns the name and version of the host application. | ||
| * | ||
| * @returns Host version info or undefined if not yet connected | ||
| */ | ||
| getHostVersion(): HostVersion | undefined; | ||
| /** | ||
| * Send a log message to the host | ||
| * | ||
| * Unlike the `log()` method which logs to the local console, | ||
| * this sends logs through the MCP protocol to the host for | ||
| * debugging and telemetry purposes. | ||
| * | ||
| * @param level - Log level | ||
| * @param data - Data to log | ||
| */ | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| /** | ||
| * Send size changed notification to host | ||
| * | ||
| * Notifies the host when the widget's size changes. | ||
| * Use this for manual size reporting. | ||
| * | ||
| * @param params - Size parameters | ||
| */ | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| /** | ||
| * Set up automatic size change notifications | ||
| * | ||
| * Creates a ResizeObserver that automatically sends size changed | ||
| * notifications to the host when the document body resizes. | ||
| * | ||
| * @returns Cleanup function to stop observing | ||
| */ | ||
| setupSizeChangedNotifications(): () => void; | ||
| /** | ||
| * Set handler for tool calls from the host | ||
| * | ||
| * When the host calls a tool exposed by this app, this handler | ||
| * will be invoked with the tool name and arguments. | ||
| * | ||
| * @param handler - Handler function for tool calls | ||
| */ | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| /** | ||
| * Set handler for listing app-exposed tools | ||
| * | ||
| * When the host requests the list of tools this app exposes, | ||
| * this handler will be invoked. | ||
| * | ||
| * @param handler - Handler function that returns tool definitions | ||
| */ | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| /** Current host context */ | ||
@@ -332,2 +523,157 @@ readonly hostContext: HostContext; | ||
| /** | ||
| * MCP Apps Protocol Constants | ||
| * | ||
| * @packageDocumentation | ||
| */ | ||
| /** | ||
| * The latest MCP Apps protocol version supported by this SDK. | ||
| * Used during client-host handshake to ensure compatibility. | ||
| */ | ||
| declare const LATEST_PROTOCOL_VERSION = "2025-11-05"; | ||
| /** | ||
| * MIME type for MCP App UI resources. | ||
| * Used when registering UI resources with the MCP server. | ||
| */ | ||
| declare const RESOURCE_MIME_TYPE = "text/html;profile=mcp-app"; | ||
| /** | ||
| * Metadata key for UI resource URIs in tool definitions. | ||
| * Used to link tools to their associated UI widgets. | ||
| */ | ||
| declare const RESOURCE_URI_META_KEY = "ui/resourceUri"; | ||
| /** | ||
| * Theme utility functions for MCP Apps | ||
| * | ||
| * Standalone functions for applying and detecting document themes. | ||
| * These can be used without React or the full client SDK. | ||
| */ | ||
| /** | ||
| * Theme value type | ||
| */ | ||
| type Theme = "light" | "dark" | "os"; | ||
| /** | ||
| * Apply a theme to the document | ||
| * | ||
| * Sets the appropriate class and data attribute on the document element. | ||
| * When "os" is specified, the system preference is detected and applied. | ||
| * | ||
| * @param theme - The theme to apply ("light", "dark", or "os") | ||
| */ | ||
| declare function applyDocumentTheme(theme: Theme): void; | ||
| /** | ||
| * Get the current document theme | ||
| * | ||
| * Detects the theme by checking the document element's class or data attribute. | ||
| * | ||
| * @returns The current theme ("light" or "dark") | ||
| */ | ||
| declare function getDocumentTheme(): "light" | "dark"; | ||
| /** | ||
| * Style utility functions for MCP Apps | ||
| * | ||
| * Standalone functions for applying host-provided styles. | ||
| * These can be used without React or the full client SDK. | ||
| */ | ||
| /** | ||
| * Apply host-provided CSS variables to the document | ||
| * | ||
| * Sets CSS custom properties on the document root element. | ||
| * Variable names are normalized to include the `--` prefix if missing. | ||
| * | ||
| * @param variables - Record of variable names to values | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * applyHostStyleVariables({ | ||
| * "primary-color": "#007bff", | ||
| * "--secondary-color": "#6c757d", | ||
| * "font-size-base": "16px", | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function applyHostStyleVariables(variables: Record<string, string>): void; | ||
| /** | ||
| * Apply host-provided font CSS | ||
| * | ||
| * Injects or updates a style element with font-related CSS. | ||
| * The style element is identified by a specific ID so it can be updated. | ||
| * | ||
| * @param css - CSS string containing @font-face rules or other font styles | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * applyHostFonts(` | ||
| * @font-face { | ||
| * font-family: 'CustomFont'; | ||
| * src: url('...') format('woff2'); | ||
| * } | ||
| * body { | ||
| * font-family: 'CustomFont', sans-serif; | ||
| * } | ||
| * `); | ||
| * ``` | ||
| */ | ||
| declare function applyHostFonts(css: string): void; | ||
| /** | ||
| * Remove host-provided font CSS | ||
| * | ||
| * Removes the style element containing host fonts if it exists. | ||
| */ | ||
| declare function removeHostFonts(): void; | ||
| /** | ||
| * Clear all host-provided CSS variables | ||
| * | ||
| * Removes all CSS custom properties that were set on the document root. | ||
| * Note: This removes ALL custom properties, not just those set by applyHostStyleVariables. | ||
| * | ||
| * @param variables - Record of variable names to clear (same format as applyHostStyleVariables) | ||
| */ | ||
| declare function clearHostStyleVariables(variables: Record<string, string>): void; | ||
| /** | ||
| * Error handling utilities for @mcp-apps-kit/ui | ||
| * | ||
| * Client-side error types for UI adapter error handling. | ||
| */ | ||
| /** | ||
| * Error codes for UI client operations | ||
| */ | ||
| declare const UIErrorCode: { | ||
| readonly CONNECTION_FAILED: "CONNECTION_FAILED"; | ||
| readonly CONNECTION_TIMEOUT: "CONNECTION_TIMEOUT"; | ||
| readonly NOT_CONNECTED: "NOT_CONNECTED"; | ||
| readonly PROTOCOL_ERROR: "PROTOCOL_ERROR"; | ||
| readonly UNSUPPORTED_OPERATION: "UNSUPPORTED_OPERATION"; | ||
| readonly TOOL_CALL_FAILED: "TOOL_CALL_FAILED"; | ||
| readonly TOOL_NOT_FOUND: "TOOL_NOT_FOUND"; | ||
| readonly STATE_ERROR: "STATE_ERROR"; | ||
| readonly UNKNOWN_ERROR: "UNKNOWN_ERROR"; | ||
| }; | ||
| type UIErrorCodeType = (typeof UIErrorCode)[keyof typeof UIErrorCode]; | ||
| /** | ||
| * Custom error class for UI client operations | ||
| * | ||
| * Provides structured error information for client-side error handling. | ||
| */ | ||
| declare class UIError extends Error { | ||
| readonly code: UIErrorCodeType; | ||
| readonly details?: Record<string, unknown> | undefined; | ||
| readonly cause?: Error | undefined; | ||
| /** | ||
| * Create a new UIError | ||
| * | ||
| * @param code - Error code from UIErrorCode enum | ||
| * @param message - Human-readable error message | ||
| * @param details - Optional additional error details | ||
| * @param cause - Optional underlying error | ||
| */ | ||
| constructor(code: UIErrorCodeType, message: string, details?: Record<string, unknown> | undefined, cause?: Error | undefined); | ||
| /** | ||
| * Format error message with code and details | ||
| */ | ||
| formatMessage(): string; | ||
| } | ||
| /** | ||
| * Protocol adapter type definitions for @mcp-apps-kit/ui | ||
@@ -499,2 +845,44 @@ * | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| /** | ||
| * Get host capabilities | ||
| * Returns capabilities advertised during handshake | ||
| */ | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| /** | ||
| * Get host version information | ||
| * Returns host name and version | ||
| */ | ||
| getHostVersion(): HostVersion | undefined; | ||
| /** | ||
| * Send a log message to the host via the protocol | ||
| * | ||
| * @param level - Log level | ||
| * @param data - Data to log | ||
| */ | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| /** | ||
| * Send size changed notification to host | ||
| * | ||
| * @param params - Size parameters (width, height) | ||
| */ | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| /** | ||
| * Subscribe to partial/streaming tool input | ||
| * | ||
| * @param handler - Callback for partial input | ||
| * @returns Unsubscribe function | ||
| */ | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| /** | ||
| * Set handler for tool calls from the host | ||
| * | ||
| * @param handler - Handler for incoming tool calls | ||
| */ | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| /** | ||
| * Set handler for listing app-exposed tools | ||
| * | ||
| * @param handler - Handler that returns tool definitions | ||
| */ | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| } | ||
@@ -702,2 +1090,3 @@ /** | ||
| private toolInputHandlers; | ||
| private toolInputPartialHandlers; | ||
| private toolCancelledHandlers; | ||
@@ -709,2 +1098,6 @@ private hostContextHandlers; | ||
| private currentToolMeta?; | ||
| private mockHostCapabilities; | ||
| private mockHostVersion; | ||
| private callToolHandler?; | ||
| private listToolsHandler?; | ||
| constructor(); | ||
@@ -768,2 +1161,29 @@ private createDefaultContext; | ||
| private notifyHostContextChange; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| /** | ||
| * Emit partial tool input (for testing streaming input) | ||
| */ | ||
| emitToolInputPartial(input: Record<string, unknown>): void; | ||
| /** | ||
| * Set mock host capabilities (for testing) | ||
| */ | ||
| setMockHostCapabilities(capabilities: Partial<HostCapabilities>): void; | ||
| /** | ||
| * Set mock host version (for testing) | ||
| */ | ||
| setMockHostVersion(version: HostVersion): void; | ||
| /** | ||
| * Simulate a tool call from host (for testing bidirectional tools) | ||
| */ | ||
| simulateHostToolCall(toolName: string, args: Record<string, unknown>): Promise<unknown>; | ||
| /** | ||
| * Simulate a list tools request from host (for testing bidirectional tools) | ||
| */ | ||
| simulateHostListTools(): Promise<unknown>; | ||
| } | ||
@@ -789,2 +1209,3 @@ | ||
| private toolInputHandlers; | ||
| private toolInputPartialHandlers; | ||
| private toolCancelledHandlers; | ||
@@ -797,2 +1218,4 @@ private hostContextHandlers; | ||
| private app?; | ||
| private callToolHandler?; | ||
| private listToolsHandler?; | ||
| constructor(); | ||
@@ -830,2 +1253,9 @@ private createDefaultContext; | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| } | ||
@@ -910,2 +1340,9 @@ | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(_handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(_handler: CallToolHandler): void; | ||
| setListToolsHandler(_handler: ListToolsHandler): void; | ||
| } | ||
@@ -987,2 +1424,2 @@ | ||
| export { type AdapterFactory, type AdapterType, type AppsClient, type ClientDebugConfig, ClientDebugLogger, type CreateClientOptions, type DebugLogLevel, type DetectedProtocol, type DeviceCapabilities, type HostContext, type HostStyles, type InferToolInputs, type InferToolOutputs, type LogEntry, McpAdapter, MockAdapter, type ModalButton, type ModalInput, type ModalOptions, type ModalResult, OpenAIAdapter, type ProtocolAdapter, type ResourceContent, type SafeAreaInsets, type ToolDefs, type ToolResult, type Viewport, clientDebugLogger, createAppsClient, createClient, detectProtocol, safeSerialize, safeStringify, shouldLog }; | ||
| export { type AdapterFactory, type AdapterType, type AppCapabilities, type AppToolDefinition, type AppsClient, type CallToolHandler, type ClientDebugConfig, ClientDebugLogger, type CreateClientOptions, type DebugLogLevel, type DetectedProtocol, type DeviceCapabilities, type HostCapabilities, type HostContext, type HostStyles, type HostVersion, type InferToolInputs, type InferToolOutputs, LATEST_PROTOCOL_VERSION, type ListToolsHandler, type LogEntry, McpAdapter, MockAdapter, type ModalButton, type ModalInput, type ModalOptions, type ModalResult, OpenAIAdapter, type ProtocolAdapter, RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY, type ResourceContent, type SafeAreaInsets, type SizeChangedParams, type Theme, type ToolDefs, type ToolResult, UIError, UIErrorCode, type UIErrorCodeType, type Viewport, applyDocumentTheme, applyHostFonts, applyHostStyleVariables, clearHostStyleVariables, clientDebugLogger, createAppsClient, createClient, detectProtocol, getDocumentTheme, removeHostFonts, safeSerialize, safeStringify, shouldLog }; |
+438
-1
@@ -5,2 +5,119 @@ /** | ||
| /** | ||
| * Host capabilities advertised during handshake. | ||
| * Protocol-agnostic interface covering features from both MCP Apps and ChatGPT. | ||
| */ | ||
| interface HostCapabilities { | ||
| /** Host accepts log messages via sendLog() */ | ||
| logging?: Record<string, never>; | ||
| /** Host supports opening external URLs via openLink() */ | ||
| openLinks?: Record<string, never>; | ||
| /** Host supports theme switching (light/dark/os) */ | ||
| theming?: { | ||
| /** Supported themes */ | ||
| themes?: ("light" | "dark" | "os")[]; | ||
| }; | ||
| /** Host supports display mode changes */ | ||
| displayModes?: { | ||
| /** Available display modes */ | ||
| modes?: ("inline" | "fullscreen" | "pip" | "panel")[]; | ||
| }; | ||
| /** Host supports state persistence */ | ||
| statePersistence?: { | ||
| /** State is persisted across sessions */ | ||
| persistent?: boolean; | ||
| /** Maximum state size in bytes */ | ||
| maxSize?: number; | ||
| }; | ||
| /** Host can proxy resource reads to MCP server (MCP Apps only) */ | ||
| serverResources?: { | ||
| /** Host supports resources/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host can proxy tool calls to MCP server (MCP Apps only) */ | ||
| serverTools?: { | ||
| /** Host supports tools/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host supports size change notifications (MCP Apps only) */ | ||
| sizeNotifications?: Record<string, never>; | ||
| /** Host supports partial/streaming tool input (MCP Apps only) */ | ||
| partialToolInput?: Record<string, never>; | ||
| /** Host supports bidirectional tools - app can expose tools to host (MCP Apps only) */ | ||
| appTools?: { | ||
| /** Host supports tools/list_changed notifications from app */ | ||
| listChanged?: boolean; | ||
| }; | ||
| /** Host supports file uploads (ChatGPT only) */ | ||
| fileUpload?: { | ||
| /** Maximum file size in bytes */ | ||
| maxSize?: number; | ||
| /** Allowed MIME types */ | ||
| allowedTypes?: string[]; | ||
| }; | ||
| /** Host provides safe area insets (ChatGPT mobile) */ | ||
| safeAreaInsets?: Record<string, never>; | ||
| /** Host supports view identification (ChatGPT only) */ | ||
| views?: { | ||
| /** Supported view types */ | ||
| types?: string[]; | ||
| }; | ||
| /** Experimental features (structure TBD) */ | ||
| experimental?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Host version information returned after connection. | ||
| */ | ||
| interface HostVersion { | ||
| /** Host application name (e.g., "Claude Desktop") */ | ||
| name: string; | ||
| /** Host application version */ | ||
| version: string; | ||
| } | ||
| /** | ||
| * App capabilities declared during initialization. | ||
| * Tells the host what this app supports. | ||
| */ | ||
| interface AppCapabilities { | ||
| /** Experimental features (structure TBD) */ | ||
| experimental?: Record<string, unknown>; | ||
| /** App exposes MCP-style tools that the host can call */ | ||
| tools?: { | ||
| /** App supports tools/list_changed notifications */ | ||
| listChanged?: boolean; | ||
| }; | ||
| } | ||
| /** | ||
| * Parameters for size changed notifications. | ||
| */ | ||
| interface SizeChangedParams { | ||
| /** Widget width in pixels */ | ||
| width: number; | ||
| /** Widget height in pixels */ | ||
| height: number; | ||
| } | ||
| /** | ||
| * Tool definition for app-exposed tools (bidirectional support). | ||
| * Used when the app exposes tools that the host can call. | ||
| */ | ||
| interface AppToolDefinition { | ||
| /** Tool name */ | ||
| name: string; | ||
| /** Tool description */ | ||
| description?: string; | ||
| /** JSON Schema for input parameters */ | ||
| inputSchema?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Handler for tool calls from the host. | ||
| * @param toolName - Name of the tool being called | ||
| * @param args - Tool arguments | ||
| * @returns Tool result | ||
| */ | ||
| type CallToolHandler = (toolName: string, args: Record<string, unknown>) => Promise<unknown>; | ||
| /** | ||
| * Handler that returns the list of tools exposed by the app. | ||
| * @returns Array of tool definitions | ||
| */ | ||
| type ListToolsHandler = () => Promise<AppToolDefinition[]>; | ||
| /** | ||
| * Viewport dimensions | ||
@@ -260,2 +377,76 @@ */ | ||
| onTeardown(handler: (reason?: string) => void): () => void; | ||
| /** | ||
| * Subscribe to partial/streaming tool input | ||
| * | ||
| * Called when the host sends partial tool arguments during streaming. | ||
| * Useful for showing real-time input as the user types or as the model generates. | ||
| * | ||
| * @param handler - Callback for partial input | ||
| * @returns Unsubscribe function | ||
| */ | ||
| onToolInputPartial(handler: (input: Record<string, unknown>) => void): () => void; | ||
| /** | ||
| * Get host capabilities | ||
| * | ||
| * Returns the capabilities advertised by the host during handshake. | ||
| * Use this to check if features like logging or server tools are supported. | ||
| * | ||
| * @returns Host capabilities or undefined if not yet connected | ||
| */ | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| /** | ||
| * Get host version information | ||
| * | ||
| * Returns the name and version of the host application. | ||
| * | ||
| * @returns Host version info or undefined if not yet connected | ||
| */ | ||
| getHostVersion(): HostVersion | undefined; | ||
| /** | ||
| * Send a log message to the host | ||
| * | ||
| * Unlike the `log()` method which logs to the local console, | ||
| * this sends logs through the MCP protocol to the host for | ||
| * debugging and telemetry purposes. | ||
| * | ||
| * @param level - Log level | ||
| * @param data - Data to log | ||
| */ | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| /** | ||
| * Send size changed notification to host | ||
| * | ||
| * Notifies the host when the widget's size changes. | ||
| * Use this for manual size reporting. | ||
| * | ||
| * @param params - Size parameters | ||
| */ | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| /** | ||
| * Set up automatic size change notifications | ||
| * | ||
| * Creates a ResizeObserver that automatically sends size changed | ||
| * notifications to the host when the document body resizes. | ||
| * | ||
| * @returns Cleanup function to stop observing | ||
| */ | ||
| setupSizeChangedNotifications(): () => void; | ||
| /** | ||
| * Set handler for tool calls from the host | ||
| * | ||
| * When the host calls a tool exposed by this app, this handler | ||
| * will be invoked with the tool name and arguments. | ||
| * | ||
| * @param handler - Handler function for tool calls | ||
| */ | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| /** | ||
| * Set handler for listing app-exposed tools | ||
| * | ||
| * When the host requests the list of tools this app exposes, | ||
| * this handler will be invoked. | ||
| * | ||
| * @param handler - Handler function that returns tool definitions | ||
| */ | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| /** Current host context */ | ||
@@ -332,2 +523,157 @@ readonly hostContext: HostContext; | ||
| /** | ||
| * MCP Apps Protocol Constants | ||
| * | ||
| * @packageDocumentation | ||
| */ | ||
| /** | ||
| * The latest MCP Apps protocol version supported by this SDK. | ||
| * Used during client-host handshake to ensure compatibility. | ||
| */ | ||
| declare const LATEST_PROTOCOL_VERSION = "2025-11-05"; | ||
| /** | ||
| * MIME type for MCP App UI resources. | ||
| * Used when registering UI resources with the MCP server. | ||
| */ | ||
| declare const RESOURCE_MIME_TYPE = "text/html;profile=mcp-app"; | ||
| /** | ||
| * Metadata key for UI resource URIs in tool definitions. | ||
| * Used to link tools to their associated UI widgets. | ||
| */ | ||
| declare const RESOURCE_URI_META_KEY = "ui/resourceUri"; | ||
| /** | ||
| * Theme utility functions for MCP Apps | ||
| * | ||
| * Standalone functions for applying and detecting document themes. | ||
| * These can be used without React or the full client SDK. | ||
| */ | ||
| /** | ||
| * Theme value type | ||
| */ | ||
| type Theme = "light" | "dark" | "os"; | ||
| /** | ||
| * Apply a theme to the document | ||
| * | ||
| * Sets the appropriate class and data attribute on the document element. | ||
| * When "os" is specified, the system preference is detected and applied. | ||
| * | ||
| * @param theme - The theme to apply ("light", "dark", or "os") | ||
| */ | ||
| declare function applyDocumentTheme(theme: Theme): void; | ||
| /** | ||
| * Get the current document theme | ||
| * | ||
| * Detects the theme by checking the document element's class or data attribute. | ||
| * | ||
| * @returns The current theme ("light" or "dark") | ||
| */ | ||
| declare function getDocumentTheme(): "light" | "dark"; | ||
| /** | ||
| * Style utility functions for MCP Apps | ||
| * | ||
| * Standalone functions for applying host-provided styles. | ||
| * These can be used without React or the full client SDK. | ||
| */ | ||
| /** | ||
| * Apply host-provided CSS variables to the document | ||
| * | ||
| * Sets CSS custom properties on the document root element. | ||
| * Variable names are normalized to include the `--` prefix if missing. | ||
| * | ||
| * @param variables - Record of variable names to values | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * applyHostStyleVariables({ | ||
| * "primary-color": "#007bff", | ||
| * "--secondary-color": "#6c757d", | ||
| * "font-size-base": "16px", | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function applyHostStyleVariables(variables: Record<string, string>): void; | ||
| /** | ||
| * Apply host-provided font CSS | ||
| * | ||
| * Injects or updates a style element with font-related CSS. | ||
| * The style element is identified by a specific ID so it can be updated. | ||
| * | ||
| * @param css - CSS string containing @font-face rules or other font styles | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * applyHostFonts(` | ||
| * @font-face { | ||
| * font-family: 'CustomFont'; | ||
| * src: url('...') format('woff2'); | ||
| * } | ||
| * body { | ||
| * font-family: 'CustomFont', sans-serif; | ||
| * } | ||
| * `); | ||
| * ``` | ||
| */ | ||
| declare function applyHostFonts(css: string): void; | ||
| /** | ||
| * Remove host-provided font CSS | ||
| * | ||
| * Removes the style element containing host fonts if it exists. | ||
| */ | ||
| declare function removeHostFonts(): void; | ||
| /** | ||
| * Clear all host-provided CSS variables | ||
| * | ||
| * Removes all CSS custom properties that were set on the document root. | ||
| * Note: This removes ALL custom properties, not just those set by applyHostStyleVariables. | ||
| * | ||
| * @param variables - Record of variable names to clear (same format as applyHostStyleVariables) | ||
| */ | ||
| declare function clearHostStyleVariables(variables: Record<string, string>): void; | ||
| /** | ||
| * Error handling utilities for @mcp-apps-kit/ui | ||
| * | ||
| * Client-side error types for UI adapter error handling. | ||
| */ | ||
| /** | ||
| * Error codes for UI client operations | ||
| */ | ||
| declare const UIErrorCode: { | ||
| readonly CONNECTION_FAILED: "CONNECTION_FAILED"; | ||
| readonly CONNECTION_TIMEOUT: "CONNECTION_TIMEOUT"; | ||
| readonly NOT_CONNECTED: "NOT_CONNECTED"; | ||
| readonly PROTOCOL_ERROR: "PROTOCOL_ERROR"; | ||
| readonly UNSUPPORTED_OPERATION: "UNSUPPORTED_OPERATION"; | ||
| readonly TOOL_CALL_FAILED: "TOOL_CALL_FAILED"; | ||
| readonly TOOL_NOT_FOUND: "TOOL_NOT_FOUND"; | ||
| readonly STATE_ERROR: "STATE_ERROR"; | ||
| readonly UNKNOWN_ERROR: "UNKNOWN_ERROR"; | ||
| }; | ||
| type UIErrorCodeType = (typeof UIErrorCode)[keyof typeof UIErrorCode]; | ||
| /** | ||
| * Custom error class for UI client operations | ||
| * | ||
| * Provides structured error information for client-side error handling. | ||
| */ | ||
| declare class UIError extends Error { | ||
| readonly code: UIErrorCodeType; | ||
| readonly details?: Record<string, unknown> | undefined; | ||
| readonly cause?: Error | undefined; | ||
| /** | ||
| * Create a new UIError | ||
| * | ||
| * @param code - Error code from UIErrorCode enum | ||
| * @param message - Human-readable error message | ||
| * @param details - Optional additional error details | ||
| * @param cause - Optional underlying error | ||
| */ | ||
| constructor(code: UIErrorCodeType, message: string, details?: Record<string, unknown> | undefined, cause?: Error | undefined); | ||
| /** | ||
| * Format error message with code and details | ||
| */ | ||
| formatMessage(): string; | ||
| } | ||
| /** | ||
| * Protocol adapter type definitions for @mcp-apps-kit/ui | ||
@@ -499,2 +845,44 @@ * | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| /** | ||
| * Get host capabilities | ||
| * Returns capabilities advertised during handshake | ||
| */ | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| /** | ||
| * Get host version information | ||
| * Returns host name and version | ||
| */ | ||
| getHostVersion(): HostVersion | undefined; | ||
| /** | ||
| * Send a log message to the host via the protocol | ||
| * | ||
| * @param level - Log level | ||
| * @param data - Data to log | ||
| */ | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| /** | ||
| * Send size changed notification to host | ||
| * | ||
| * @param params - Size parameters (width, height) | ||
| */ | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| /** | ||
| * Subscribe to partial/streaming tool input | ||
| * | ||
| * @param handler - Callback for partial input | ||
| * @returns Unsubscribe function | ||
| */ | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| /** | ||
| * Set handler for tool calls from the host | ||
| * | ||
| * @param handler - Handler for incoming tool calls | ||
| */ | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| /** | ||
| * Set handler for listing app-exposed tools | ||
| * | ||
| * @param handler - Handler that returns tool definitions | ||
| */ | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| } | ||
@@ -702,2 +1090,3 @@ /** | ||
| private toolInputHandlers; | ||
| private toolInputPartialHandlers; | ||
| private toolCancelledHandlers; | ||
@@ -709,2 +1098,6 @@ private hostContextHandlers; | ||
| private currentToolMeta?; | ||
| private mockHostCapabilities; | ||
| private mockHostVersion; | ||
| private callToolHandler?; | ||
| private listToolsHandler?; | ||
| constructor(); | ||
@@ -768,2 +1161,29 @@ private createDefaultContext; | ||
| private notifyHostContextChange; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| /** | ||
| * Emit partial tool input (for testing streaming input) | ||
| */ | ||
| emitToolInputPartial(input: Record<string, unknown>): void; | ||
| /** | ||
| * Set mock host capabilities (for testing) | ||
| */ | ||
| setMockHostCapabilities(capabilities: Partial<HostCapabilities>): void; | ||
| /** | ||
| * Set mock host version (for testing) | ||
| */ | ||
| setMockHostVersion(version: HostVersion): void; | ||
| /** | ||
| * Simulate a tool call from host (for testing bidirectional tools) | ||
| */ | ||
| simulateHostToolCall(toolName: string, args: Record<string, unknown>): Promise<unknown>; | ||
| /** | ||
| * Simulate a list tools request from host (for testing bidirectional tools) | ||
| */ | ||
| simulateHostListTools(): Promise<unknown>; | ||
| } | ||
@@ -789,2 +1209,3 @@ | ||
| private toolInputHandlers; | ||
| private toolInputPartialHandlers; | ||
| private toolCancelledHandlers; | ||
@@ -797,2 +1218,4 @@ private hostContextHandlers; | ||
| private app?; | ||
| private callToolHandler?; | ||
| private listToolsHandler?; | ||
| constructor(); | ||
@@ -830,2 +1253,9 @@ private createDefaultContext; | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(handler: CallToolHandler): void; | ||
| setListToolsHandler(handler: ListToolsHandler): void; | ||
| } | ||
@@ -910,2 +1340,9 @@ | ||
| getToolMeta(): Record<string, unknown> | undefined; | ||
| getHostCapabilities(): HostCapabilities | undefined; | ||
| getHostVersion(): HostVersion | undefined; | ||
| sendLog(level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency", data: unknown): Promise<void>; | ||
| sendSizeChanged(params: SizeChangedParams): Promise<void>; | ||
| onToolInputPartial(_handler: (input: unknown) => void): () => void; | ||
| setCallToolHandler(_handler: CallToolHandler): void; | ||
| setListToolsHandler(_handler: ListToolsHandler): void; | ||
| } | ||
@@ -987,2 +1424,2 @@ | ||
| export { type AdapterFactory, type AdapterType, type AppsClient, type ClientDebugConfig, ClientDebugLogger, type CreateClientOptions, type DebugLogLevel, type DetectedProtocol, type DeviceCapabilities, type HostContext, type HostStyles, type InferToolInputs, type InferToolOutputs, type LogEntry, McpAdapter, MockAdapter, type ModalButton, type ModalInput, type ModalOptions, type ModalResult, OpenAIAdapter, type ProtocolAdapter, type ResourceContent, type SafeAreaInsets, type ToolDefs, type ToolResult, type Viewport, clientDebugLogger, createAppsClient, createClient, detectProtocol, safeSerialize, safeStringify, shouldLog }; | ||
| export { type AdapterFactory, type AdapterType, type AppCapabilities, type AppToolDefinition, type AppsClient, type CallToolHandler, type ClientDebugConfig, ClientDebugLogger, type CreateClientOptions, type DebugLogLevel, type DetectedProtocol, type DeviceCapabilities, type HostCapabilities, type HostContext, type HostStyles, type HostVersion, type InferToolInputs, type InferToolOutputs, LATEST_PROTOCOL_VERSION, type ListToolsHandler, type LogEntry, McpAdapter, MockAdapter, type ModalButton, type ModalInput, type ModalOptions, type ModalResult, OpenAIAdapter, type ProtocolAdapter, RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY, type ResourceContent, type SafeAreaInsets, type SizeChangedParams, type Theme, type ToolDefs, type ToolResult, UIError, UIErrorCode, type UIErrorCodeType, type Viewport, applyDocumentTheme, applyHostFonts, applyHostStyleVariables, clearHostStyleVariables, clientDebugLogger, createAppsClient, createClient, detectProtocol, getDocumentTheme, removeHostFonts, safeSerialize, safeStringify, shouldLog }; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| import {App}from'@modelcontextprotocol/ext-apps';var y={debug:0,info:1,warn:2,error:3};function x(n,e){return y[n]>=y[e]}function C(){let n=new WeakSet;return (e,t)=>{if(typeof t=="object"&&t!==null){if(n.has(t))return "[Circular]";n.add(t);}return t}}function k(n){if(n==null||typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(n instanceof Error)return {name:n.name,message:n.message,stack:n.stack};try{return JSON.stringify(n),n}catch{try{let e=JSON.stringify(n,C());return JSON.parse(e)}catch{return "[Unserializable]"}}}function b(n){if(n===void 0)return "undefined";if(n===null)return "null";if(typeof n=="string")return n;if(n instanceof Error)return `${n.name}: ${n.message}`;try{return JSON.stringify(n,C())}catch{return "[Unstringifiable]"}}var f=class{constructor(e={}){this.adapter=null;this.buffer=[];this.flushTimer=null;this.isFlushing=false;this.mcpTransportFailed=false;this.config={enabled:e.enabled??false,level:e.level??"info",batchSize:e.batchSize??10,maxBufferSize:e.maxBufferSize??100,flushIntervalMs:e.flushIntervalMs??5e3,source:e.source??"mcp-apps-ui"};}setAdapter(e){this.adapter=e,this.mcpTransportFailed=false;}configure(e){e.enabled!==void 0&&(this.config.enabled=e.enabled),e.level!==void 0&&(this.config.level=e.level),e.batchSize!==void 0&&(this.config.batchSize=e.batchSize),e.maxBufferSize!==void 0&&(this.config.maxBufferSize=e.maxBufferSize),e.flushIntervalMs!==void 0&&(this.config.flushIntervalMs=e.flushIntervalMs,this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.scheduleFlush()),e.source!==void 0&&(this.config.source=e.source);}canUseMcpTransport(){return this.config.enabled&&!this.mcpTransportFailed&&this.adapter?.isConnected()===true}createEntry(e,t,o){return {level:e,message:t,data:o!==void 0?k(o):void 0,timestamp:new Date().toISOString(),source:this.config.source}}scheduleFlush(){this.flushTimer||this.buffer.length===0||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush();},this.config.flushIntervalMs));}async flush(){if(this.isFlushing||this.buffer.length===0)return;if(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),!this.canUseMcpTransport()){for(let t of this.buffer)this.outputToConsole(t);this.buffer=[];return}this.isFlushing=true;let e=[...this.buffer];this.buffer=[];try{this.adapter&&await this.adapter.callTool("log_debug",{entries:e});}catch{this.mcpTransportFailed||(this.mcpTransportFailed=true,console.info("[ClientDebugLogger] MCP log transport unavailable, using console fallback"));for(let t of e)this.outputToConsole(t);}finally{this.isFlushing=false,this.buffer.length>0&&this.scheduleFlush();}}outputToConsole(e){let t=`[${e.timestamp}] [${e.level.toUpperCase()}]`,o=e.data!==void 0?`${e.message} ${b(e.data)}`:e.message,s=`${t} ${o}`;try{switch(e.level){case "debug":console.debug(s);break;case "info":console.info(s);break;case "warn":console.warn(s);break;case "error":console.error(s);break}}catch{}}addToBuffer(e){if(this.buffer.length>=this.config.maxBufferSize){let t=this.buffer.shift();t&&this.outputToConsole(t);}if(this.buffer.push(e),e.level==="error"){this.flush();return}if(this.buffer.length>=this.config.batchSize){this.flush();return}this.scheduleFlush();}log(e,t,o){if(!x(e,this.config.level))return;let s=this.createEntry(e,t,o);if(!this.canUseMcpTransport()){this.outputToConsole(s);return}this.addToBuffer(s);}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}destroy(){if(this.buffer.length>0){for(let e of this.buffer)this.outputToConsole(e);this.buffer=[];}this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.adapter=null;}},h=new f;var d=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}async connect(){this.connected=true,console.log("[MockAdapter] Connected");}isConnected(){return this.connected}async callTool(e,t){console.log(`[MockAdapter] callTool("${e}",`,t,")");let o={_mock:true,tool:e,args:t,timestamp:Date.now()};return this.currentToolOutput=o,o}async sendMessage(e){console.log("[MockAdapter] sendMessage:",e);}async openLink(e){console.log(`[MockAdapter] openLink("${e}")`);}async requestDisplayMode(e){return console.log(`[MockAdapter] requestDisplayMode("${e}")`),this.context={...this.context,displayMode:e},this.notifyHostContextChange(),{mode:e}}requestClose(){console.log("[MockAdapter] requestClose()");}getState(){return this.state}setState(e){this.state=e,console.log("[MockAdapter] setState:",e);}async readResource(e){return console.log(`[MockAdapter] readResource("${e}")`),{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MockAdapter]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}emitToolResult(e){this.currentToolOutput=e;for(let t of this.toolResultHandlers)t(e);}emitToolInput(e){this.currentToolInput=e;for(let t of this.toolInputHandlers)t(e);}setHostContext(e){this.context={...this.context,...e},this.notifyHostContextChange();}emitContextChange(e){this.context=e,this.notifyHostContextChange();}setToolInput(e){this.currentToolInput=e;}emitToolCancelled(e){for(let t of this.toolCancelledHandlers)t(e);}emitTeardown(e){for(let t of this.teardownHandlers)t(e);}notifyHostContextChange(){for(let e of this.hostContextHandlers)e(this.context);}};var H={parse:n=>n},p=class{constructor(){this.connected=false;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"desktop"}}async connect(){if(this.connected)return;if(typeof window>"u"){this.connected=true;return}this.app=new App({name:"@mcp-apps-kit/ui",version:"0.0.0"},{}),this.app.onerror=t=>{this.log("error",t);},this.app.onhostcontextchanged=t=>{let o=t.hostContext??t;this.context=this.mapHostContext(o),this.currentToolMeta=this.extractToolMeta(o);for(let s of this.hostContextHandlers)s(this.context);},this.app.ontoolinput=t=>{let o=t.arguments;if(o){this.currentToolInput=o;for(let s of this.toolInputHandlers)s(o);}},this.app.ontoolresult=t=>{let o=this.extractToolOutput(t);this.currentToolOutput=o;for(let s of this.toolResultHandlers)s(o);},this.app.ontoolcancelled=t=>{let o=t.reason;for(let s of this.toolCancelledHandlers)s(o);},this.app.onteardown=async t=>{let o=t.reason;for(let s of this.teardownHandlers)s(o);return {}},await this.app.connect();let e=this.app.getHostContext();e&&(this.context=this.mapHostContext(e),this.currentToolMeta=this.extractToolMeta(e)),this.connected=true;}isConnected(){return this.connected}mapHostContext(e){let t=e??{},o=this.createDefaultContext(),s=t.theme==="dark"?"dark":t.theme==="light"?"light":o.theme,r=t.displayMode==="fullscreen"||t.displayMode==="pip"||t.displayMode==="inline"?t.displayMode:o.displayMode,i=Array.isArray(t.availableDisplayModes)?t.availableDisplayModes.filter(u=>typeof u=="string"):o.availableDisplayModes,g=(u=>u!==null&&typeof u=="object"&&!Array.isArray(u))(t.viewport)?{...o.viewport,...t.viewport}:o.viewport,l=typeof t.locale=="string"?t.locale:o.locale,v=typeof t.timeZone=="string"?t.timeZone:o.timeZone,T=o.platform;return {...o,theme:s,displayMode:r,availableDisplayModes:i,viewport:g,locale:l,timeZone:v,platform:T,userAgent:typeof t.userAgent=="string"?t.userAgent:o.userAgent,deviceCapabilities:t.deviceCapabilities,safeAreaInsets:t.safeAreaInsets,styles:t.styles,view:typeof t.view=="string"?t.view:o.view}}extractToolMeta(e){if(e===null||typeof e!="object")return;let t=e;if(!(!t.toolInfo||typeof t.toolInfo!="object"))return {toolInfo:t.toolInfo}}extractToolOutput(e){let t=e.structuredContent,o=e._meta,s=t&&typeof t=="object"&&!Array.isArray(t)?t:{};if(o&&typeof o=="object"&&!Array.isArray(o))return {...s,_meta:o};if(Object.keys(s).length===0){let r=e.content;if(Array.isArray(r)&&r.length>0){let i=r[0];if(i?.type==="text"&&typeof i.text=="string")try{let a=JSON.parse(i.text);if(a!==null&&typeof a=="object"&&!Array.isArray(a))return a}catch{}}}return s}async callTool(e,t){if(!this.app)throw new Error("MCP Apps adapter not connected");let o=await this.app.callServerTool({name:e,arguments:t});return this.extractToolOutput(o)}async sendMessage(e){if(!this.app)throw new Error("MCP Apps adapter not connected");if(e.type!=="text")throw new Error(`Unsupported message content type: ${e.type}`);await this.app.sendMessage({role:"user",content:[{type:"text",text:e.text}]});}async openLink(e){if(!this.app)throw new Error("MCP Apps adapter not connected");await this.app.openLink({url:e});}async requestDisplayMode(e){if(!this.app)throw new Error("MCP Apps adapter not connected");return await this.app.requestDisplayMode({mode:e})}requestClose(){}getState(){return null}setState(e){}async readResource(e){if(!this.app)throw new Error("MCP Apps adapter not connected");let o=await this.app.request.bind(this.app)({method:"resources/read",params:{uri:e}},H);return {contents:(Array.isArray(o.contents)?o.contents:[]).map(s=>{let r={uri:s.uri,mimeType:s.mimeType??"application/octet-stream"};if("text"in s&&typeof s.text=="string")return {...r,text:s.text};if("blob"in s&&typeof s.blob=="string"){let i=Uint8Array.from(atob(s.blob),a=>a.charCodeAt(0));return {...r,blob:i}}return r})}}log(e,t){if(this.app){let r={level:["debug","info","notice","warning","error","critical","alert","emergency"].includes(e)?e:"info",data:t,logger:"@mcp-apps-kit/ui"};try{this.app.sendLog(r);return}catch{}}({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MCP Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}};var c=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}readContextFromSDK(){let e=this.getOpenAI();if(!e)return;let t=typeof window<"u";if(typeof e.theme=="string"&&(this.context.theme=e.theme),typeof e.displayMode=="string"&&(this.context.displayMode=e.displayMode),typeof e.locale=="string"&&(this.context.locale=e.locale),typeof e.userAgent=="string"&&Object.assign(this.context,{userAgent:e.userAgent}),typeof e.view=="string"&&(this.context.view=e.view),e.safeArea&&typeof e.safeArea=="object"){let o=e.safeArea;this.context.safeAreaInsets={top:typeof o.top=="number"?o.top:0,right:typeof o.right=="number"?o.right:0,bottom:typeof o.bottom=="number"?o.bottom:0,left:typeof o.left=="number"?o.left:0};}typeof e.maxHeight=="number"&&(this.context.viewport={width:t?window.innerWidth:800,height:e.maxHeight}),console.log("[OpenAI Adapter] Read context from SDK:",this.context);}notifyContextChange(){console.log(`[OpenAI Adapter] Notifying ${String(this.hostContextHandlers.size)} context change handlers`);let e={...this.context};for(let t of this.hostContextHandlers)t(e);}getOpenAI(){return typeof window<"u"&&"openai"in window?window.openai:null}async connect(){await this.waitForOpenAI();let e=this.getOpenAI();e&&(console.log("[OpenAI Adapter] Available SDK methods:",Object.keys(e)),this.readContextFromSDK(),typeof e.getToolOutput=="function"?(this.currentToolOutput=e.getToolOutput(),console.log("[OpenAI Adapter] Got tool output from SDK")):e.toolOutput?(this.currentToolOutput=e.toolOutput,console.log("[OpenAI Adapter] Got tool output from SDK property")):e.result&&(this.currentToolOutput=e.result,console.log("[OpenAI Adapter] Got result from SDK")),typeof e.getToolInput=="function"?this.currentToolInput=e.getToolInput():e.toolInput?this.currentToolInput=e.toolInput:e.input&&(this.currentToolInput=e.input),typeof e.init=="function"&&await e.init()),this.setupGlobalsListener(),this.connected=true;}setupGlobalsListener(){typeof window>"u"||(this.globalsHandler=e=>{let t=e.data;(t==="openai:set_globals"||typeof t=="object"&&t!==null&&"type"in t&&t.type==="openai:set_globals"||typeof t=="object"&&t!==null&&"message"in t&&t.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals event, refreshing context"),setTimeout(()=>{let s=this.context.theme,r=this.context.locale,i=this.context.displayMode;this.readContextFromSDK(),(this.context.theme!==s||this.context.locale!==r||this.context.displayMode!==i)&&(console.log("[OpenAI Adapter] Context changed, notifying handlers"),this.notifyContextChange());},10));},window.addEventListener("message",this.globalsHandler));}async waitForOpenAI(e=5e3){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai already available");return}return console.log("[OpenAI Adapter] Waiting for window.openai..."),new Promise(t=>{let o=Date.now(),s=false,r=()=>{s||(s=true,window.removeEventListener("message",a),t());},i=()=>{if(!s){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai found via polling"),r();return}if(Date.now()-o>e){console.warn("[OpenAI Adapter] window.openai not found after timeout, proceeding anyway"),r();return}setTimeout(i,50);}},a=g=>{let l=g.data;(l==="openai:set_globals"||typeof l=="object"&&l!==null&&"type"in l&&l.type==="openai:set_globals"||typeof l=="object"&&l!==null&&"message"in l&&l.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals message"),setTimeout(()=>{this.getOpenAI()?(console.log("[OpenAI Adapter] window.openai available after set_globals"),r()):console.log("[OpenAI Adapter] window.openai still not available after set_globals, continuing poll");},50));};window.addEventListener("message",a),i();})}isConnected(){return this.connected}async callTool(e,t){let o=this.getOpenAI();if(o&&typeof o.callTool=="function")return o.callTool(e,t);throw new Error("OpenAI SDK not available")}async sendMessage(e){let t=this.getOpenAI();t&&typeof t.sendMessage=="function"&&await t.sendMessage(e);}async openLink(e){let t=this.getOpenAI();t&&typeof t.openLink=="function"?await t.openLink(e):window.open(e,"_blank");}async requestDisplayMode(e){let t=this.getOpenAI();if(t&&typeof t.requestDisplayMode=="function"){let o=await t.requestDisplayMode({mode:e});return this.context={...this.context,displayMode:o.mode},this.notifyContextChange(),o}return this.context={...this.context,displayMode:e},this.notifyContextChange(),{mode:e}}requestClose(){let e=this.getOpenAI();e&&typeof e.close=="function"&&e.close();}getState(){return this.state}setState(e){this.state=e;let t=this.getOpenAI();t&&typeof t.setState=="function"&&t.setState(e);}async uploadFile(e){let t=this.getOpenAI();if(t&&typeof t.uploadFile=="function")return t.uploadFile(e);throw new Error("File upload not supported")}async getFileDownloadUrl(e){let t=this.getOpenAI();if(t&&typeof t.getFileDownloadUrl=="function")return t.getFileDownloadUrl(e);throw new Error("File download not supported")}async readResource(e){let t=this.getOpenAI();return t&&typeof t.readResource=="function"?t.readResource(e):{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[ChatGPT Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),console.log(`[OpenAI Adapter] Host context handler added, total: ${String(this.hostContextHandlers.size)}`),()=>{this.hostContextHandlers.delete(e),console.log(`[OpenAI Adapter] Host context handler removed, total: ${String(this.hostContextHandlers.size)}`);}}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}};function S(){let n=window.location.href;if(n.includes("/api/apps/chatgpt/")||n.includes("chatgpt")||n.includes("sandbox-proxy")||n.includes("widget-content"))return true;let e=document.referrer;return !!(e.includes("chatgpt")||e.includes("openai.com"))}function w(){return typeof window>"u"?"mock":"openai"in window||S()?"openai":window.parent!==window?"mcp":"mock"}function m(n){return {async callTool(t,o){return await n.callTool(t,o)},async sendMessage(t){await n.sendMessage(t);},async sendFollowUpMessage(t){await n.sendMessage({type:"text",text:t});},async openLink(t){await n.openLink(t);},async requestDisplayMode(t){return n.requestDisplayMode(t)},requestClose(){n.requestClose();},getState(){return n.getState()},setState(t){n.setState(t);},...n.uploadFile&&{uploadFile:t=>{if(n.uploadFile)return n.uploadFile(t);throw new Error("uploadFile not supported")}},...n.getFileDownloadUrl&&{getFileDownloadUrl:t=>{if(n.getFileDownloadUrl)return n.getFileDownloadUrl(t);throw new Error("getFileDownloadUrl not supported")}},async readResource(t){return n.readResource(t)},log(t,o){n.log(t,o);},onToolResult(t){return n.onToolResult(t)},onToolInput(t){return n.onToolInput(t)},onToolCancelled(t){return n.onToolCancelled(t)},onHostContextChange(t){return n.onHostContextChange(t)},onTeardown(t){return n.onTeardown(t)},get hostContext(){return n.getHostContext()},get toolInput(){return n.getToolInput()},get toolOutput(){return n.getToolOutput()},get toolMeta(){return n.getToolMeta()}}}function I(n){switch(n){case "mcp":return new p;case "openai":return new c;case "mock":return new d;default:throw new Error(`Unknown adapter type: ${n}`)}}async function j(n){let e=n?.forceAdapter??w();if(!["mcp","openai","mock"].includes(e))throw new Error(`Unknown adapter type: ${e}`);let t=I(e);return await t.connect(),h.setAdapter(t),m(t)}export{f as ClientDebugLogger,p as McpAdapter,d as MockAdapter,c as OpenAIAdapter,h as clientDebugLogger,m as createAppsClient,j as createClient,w as detectProtocol,k as safeSerialize,b as safeStringify,x as shouldLog};//# sourceMappingURL=index.js.map | ||
| import {App}from'@modelcontextprotocol/ext-apps';var L="2025-11-05",D="text/html;profile=mcp-app",F="ui/resourceUri";function x(o){if(typeof document>"u")return;let e=o==="os"?typeof window<"u"&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":o;document.documentElement.classList.remove("light","dark"),document.documentElement.classList.add(e),document.documentElement.setAttribute("data-theme",e);}function H(){if(typeof document>"u")return "light";let o=document.documentElement.getAttribute("data-theme");return o==="dark"||o==="light"?o:document.documentElement.classList.contains("dark")?"dark":"light"}var w="mcp-apps-host-fonts";function k(o){if(typeof document>"u")return;let e=document.documentElement;for(let[t,n]of Object.entries(o)){let s=t.startsWith("--")?t:`--${t}`;e.style.setProperty(s,n);}}function b(o){if(typeof document>"u")return;let e=document.getElementById(w);e||(e=document.createElement("style"),e.id=w,document.head.appendChild(e)),e.textContent=o;}function A(){if(typeof document>"u")return;let o=document.getElementById(w);o&&o.remove();}function I(o){if(typeof document>"u")return;let e=document.documentElement;for(let t of Object.keys(o)){let n=t.startsWith("--")?t:`--${t}`;e.style.removeProperty(n);}}var u={CONNECTION_FAILED:"CONNECTION_FAILED",CONNECTION_TIMEOUT:"CONNECTION_TIMEOUT",NOT_CONNECTED:"NOT_CONNECTED",PROTOCOL_ERROR:"PROTOCOL_ERROR",UNSUPPORTED_OPERATION:"UNSUPPORTED_OPERATION",TOOL_CALL_FAILED:"TOOL_CALL_FAILED",TOOL_NOT_FOUND:"TOOL_NOT_FOUND",STATE_ERROR:"STATE_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR"},d=class extends Error{constructor(t,n,s,r){super(n);this.code=t;this.details=s;this.cause=r;this.name="UIError";}formatMessage(){let t=`[${this.code}] ${this.message}`;return this.details&&(t+=` ${JSON.stringify(this.details)}`),t}};var S={debug:0,info:1,warn:2,error:3};function O(o,e){return S[o]>=S[e]}function R(){let o=new WeakSet;return (e,t)=>{if(typeof t=="object"&&t!==null){if(o.has(t))return "[Circular]";o.add(t);}return t}}function M(o){if(o==null||typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o;if(o instanceof Error)return {name:o.name,message:o.message,stack:o.stack};try{return JSON.stringify(o),o}catch{try{let e=JSON.stringify(o,R());return JSON.parse(e)}catch{return "[Unserializable]"}}}function P(o){if(o===void 0)return "undefined";if(o===null)return "null";if(typeof o=="string")return o;if(o instanceof Error)return `${o.name}: ${o.message}`;try{return JSON.stringify(o,R())}catch{return "[Unstringifiable]"}}var h=class{constructor(e={}){this.adapter=null;this.buffer=[];this.flushTimer=null;this.isFlushing=false;this.mcpTransportFailed=false;this.config={enabled:e.enabled??false,level:e.level??"info",batchSize:e.batchSize??10,maxBufferSize:e.maxBufferSize??100,flushIntervalMs:e.flushIntervalMs??5e3,source:e.source??"mcp-apps-ui"};}setAdapter(e){this.adapter=e,this.mcpTransportFailed=false;}configure(e){e.enabled!==void 0&&(this.config.enabled=e.enabled),e.level!==void 0&&(this.config.level=e.level),e.batchSize!==void 0&&(this.config.batchSize=e.batchSize),e.maxBufferSize!==void 0&&(this.config.maxBufferSize=e.maxBufferSize),e.flushIntervalMs!==void 0&&(this.config.flushIntervalMs=e.flushIntervalMs,this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.scheduleFlush()),e.source!==void 0&&(this.config.source=e.source);}canUseMcpTransport(){return this.config.enabled&&!this.mcpTransportFailed&&this.adapter?.isConnected()===true}createEntry(e,t,n){return {level:e,message:t,data:n!==void 0?M(n):void 0,timestamp:new Date().toISOString(),source:this.config.source}}scheduleFlush(){this.flushTimer||this.buffer.length===0||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flush();},this.config.flushIntervalMs));}async flush(){if(this.isFlushing||this.buffer.length===0)return;if(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),!this.canUseMcpTransport()){for(let t of this.buffer)this.outputToConsole(t);this.buffer=[];return}this.isFlushing=true;let e=[...this.buffer];this.buffer=[];try{this.adapter&&await this.adapter.callTool("log_debug",{entries:e});}catch{this.mcpTransportFailed||(this.mcpTransportFailed=true,console.info("[ClientDebugLogger] MCP log transport unavailable, using console fallback"));for(let t of e)this.outputToConsole(t);}finally{this.isFlushing=false,this.buffer.length>0&&this.scheduleFlush();}}outputToConsole(e){let t=`[${e.timestamp}] [${e.level.toUpperCase()}]`,n=e.data!==void 0?`${e.message} ${P(e.data)}`:e.message,s=`${t} ${n}`;try{switch(e.level){case "debug":console.debug(s);break;case "info":console.info(s);break;case "warn":console.warn(s);break;case "error":console.error(s);break}}catch{}}addToBuffer(e){if(this.buffer.length>=this.config.maxBufferSize){let t=this.buffer.shift();t&&this.outputToConsole(t);}if(this.buffer.push(e),e.level==="error"){this.flush();return}if(this.buffer.length>=this.config.batchSize){this.flush();return}this.scheduleFlush();}log(e,t,n){if(!O(e,this.config.level))return;let s=this.createEntry(e,t,n);if(!this.canUseMcpTransport()){this.outputToConsole(s);return}this.addToBuffer(s);}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}destroy(){if(this.buffer.length>0){for(let e of this.buffer)this.outputToConsole(e);this.buffer=[];}this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.adapter=null;}},v=new h;var c=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolInputPartialHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.mockHostCapabilities={logging:{},openLinks:{},theming:{themes:["light","dark","os"]},displayModes:{modes:["inline","fullscreen","pip","panel"]},statePersistence:{persistent:true},serverTools:{listChanged:false},serverResources:{listChanged:false},sizeNotifications:{},partialToolInput:{},appTools:{listChanged:false},fileUpload:{},safeAreaInsets:{},views:{}};this.mockHostVersion={name:"MockHost",version:"1.0.0"};this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}async connect(){this.connected=true,console.log("[MockAdapter] Connected");}isConnected(){return this.connected}async callTool(e,t){console.log(`[MockAdapter] callTool("${e}",`,t,")");let n={_mock:true,tool:e,args:t,timestamp:Date.now()};return this.currentToolOutput=n,n}async sendMessage(e){console.log("[MockAdapter] sendMessage:",e);}async openLink(e){console.log(`[MockAdapter] openLink("${e}")`);}async requestDisplayMode(e){return console.log(`[MockAdapter] requestDisplayMode("${e}")`),this.context={...this.context,displayMode:e},this.notifyHostContextChange(),{mode:e}}requestClose(){console.log("[MockAdapter] requestClose()");}getState(){return this.state}setState(e){this.state=e,console.log("[MockAdapter] setState:",e);}async readResource(e){return console.log(`[MockAdapter] readResource("${e}")`),{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MockAdapter]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}emitToolResult(e){this.currentToolOutput=e;for(let t of this.toolResultHandlers)t(e);}emitToolInput(e){this.currentToolInput=e;for(let t of this.toolInputHandlers)t(e);}setHostContext(e){this.context={...this.context,...e},this.notifyHostContextChange();}emitContextChange(e){this.context=e,this.notifyHostContextChange();}setToolInput(e){this.currentToolInput=e;}emitToolCancelled(e){for(let t of this.toolCancelledHandlers)t(e);}emitTeardown(e){for(let t of this.teardownHandlers)t(e);}notifyHostContextChange(){for(let e of this.hostContextHandlers)e(this.context);}getHostCapabilities(){return this.mockHostCapabilities}getHostVersion(){return this.mockHostVersion}async sendLog(e,t){console.log(`[MockAdapter] sendLog(${e}):`,t);}async sendSizeChanged(e){console.log("[MockAdapter] sendSizeChanged:",e);}onToolInputPartial(e){return this.toolInputPartialHandlers.add(e),()=>this.toolInputPartialHandlers.delete(e)}setCallToolHandler(e){this.callToolHandler=e,console.log("[MockAdapter] setCallToolHandler: handler registered");}setListToolsHandler(e){this.listToolsHandler=e,console.log("[MockAdapter] setListToolsHandler: handler registered");}emitToolInputPartial(e){for(let t of this.toolInputPartialHandlers)t(e);}setMockHostCapabilities(e){this.mockHostCapabilities={...this.mockHostCapabilities,...e};}setMockHostVersion(e){this.mockHostVersion=e;}async simulateHostToolCall(e,t){if(!this.callToolHandler)throw new d(u.TOOL_NOT_FOUND,"No call tool handler registered");return this.callToolHandler(e,t)}async simulateHostListTools(){return this.listToolsHandler?this.listToolsHandler():{tools:[]}}};var N={parse:o=>o},g=class{constructor(){this.connected=false;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolInputPartialHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"desktop"}}async connect(){if(this.connected)return;if(typeof window>"u"){this.connected=true;return}this.app=new App({name:"@mcp-apps-kit/ui",version:"0.0.0"},{}),this.app.onerror=t=>{this.log("error",t);},this.app.onhostcontextchanged=t=>{let n=t.hostContext??t;this.context=this.mapHostContext(n),this.currentToolMeta=this.extractToolMeta(n);for(let s of this.hostContextHandlers)s(this.context);},this.app.ontoolinput=t=>{let n=t.arguments;if(n){this.currentToolInput=n;for(let s of this.toolInputHandlers)s(n);}},this.app.ontoolinputpartial=t=>{let n=t.arguments;if(n)for(let s of this.toolInputPartialHandlers)s(n);},this.app.oncalltool=async t=>{let{name:n,arguments:s}=t;try{if(this.callToolHandler){let r=await this.callToolHandler(n,s??{});return {content:[{type:"text",text:JSON.stringify(r)}]}}return {content:[{type:"text",text:`No handler registered for tool: ${n}`}],isError:!0}}catch(r){return {content:[{type:"text",text:r instanceof Error?r.message:String(r)}],isError:true}}},this.app.onlisttools=async()=>this.listToolsHandler?{tools:(await this.listToolsHandler()).map(n=>n.name)}:{tools:[]},this.app.ontoolresult=t=>{let n=this.extractToolOutput(t);this.currentToolOutput=n;for(let s of this.toolResultHandlers)s(n);},this.app.ontoolcancelled=t=>{let n=t.reason;for(let s of this.toolCancelledHandlers)s(n);},this.app.onteardown=async t=>{let n=t.reason;for(let s of this.teardownHandlers)s(n);return {}},await this.app.connect();let e=this.app.getHostContext();e&&(this.context=this.mapHostContext(e),this.currentToolMeta=this.extractToolMeta(e)),this.connected=true;}isConnected(){return this.connected}mapHostContext(e){let t=e??{},n=this.createDefaultContext(),s=t.theme==="dark"?"dark":t.theme==="light"?"light":n.theme,r=t.displayMode==="fullscreen"||t.displayMode==="pip"||t.displayMode==="inline"?t.displayMode:n.displayMode,i=Array.isArray(t.availableDisplayModes)?t.availableDisplayModes.filter(p=>typeof p=="string"):n.availableDisplayModes,m=(p=>p!==null&&typeof p=="object"&&!Array.isArray(p))(t.viewport)?{...n.viewport,...t.viewport}:n.viewport,l=typeof t.locale=="string"?t.locale:n.locale,T=typeof t.timeZone=="string"?t.timeZone:n.timeZone,E=n.platform;return {...n,theme:s,displayMode:r,availableDisplayModes:i,viewport:m,locale:l,timeZone:T,platform:E,userAgent:typeof t.userAgent=="string"?t.userAgent:n.userAgent,deviceCapabilities:t.deviceCapabilities,safeAreaInsets:t.safeAreaInsets,styles:t.styles,view:typeof t.view=="string"?t.view:n.view}}extractToolMeta(e){if(e===null||typeof e!="object")return;let t=e;if(!(!t.toolInfo||typeof t.toolInfo!="object"))return {toolInfo:t.toolInfo}}extractToolOutput(e){let t=e.structuredContent,n=e._meta,s=t&&typeof t=="object"&&!Array.isArray(t)?t:{};if(n&&typeof n=="object"&&!Array.isArray(n))return {...s,_meta:n};if(Object.keys(s).length===0){let r=e.content;if(Array.isArray(r)&&r.length>0){let i=r[0];if(i?.type==="text"&&typeof i.text=="string")try{let a=JSON.parse(i.text);if(a!==null&&typeof a=="object"&&!Array.isArray(a))return a}catch{}}}return s}async callTool(e,t){if(!this.app)throw new Error("MCP Apps adapter not connected");let n=await this.app.callServerTool({name:e,arguments:t});return this.extractToolOutput(n)}async sendMessage(e){if(!this.app)throw new Error("MCP Apps adapter not connected");if(e.type!=="text")throw new Error(`Unsupported message content type: ${e.type}`);await this.app.sendMessage({role:"user",content:[{type:"text",text:e.text}]});}async openLink(e){if(!this.app)throw new Error("MCP Apps adapter not connected");await this.app.openLink({url:e});}async requestDisplayMode(e){if(!this.app)throw new Error("MCP Apps adapter not connected");return await this.app.requestDisplayMode({mode:e})}requestClose(){}getState(){return null}setState(e){}async readResource(e){if(!this.app)throw new Error("MCP Apps adapter not connected");let n=await this.app.request.bind(this.app)({method:"resources/read",params:{uri:e}},N);return {contents:(Array.isArray(n.contents)?n.contents:[]).map(s=>{let r={uri:s.uri,mimeType:s.mimeType??"application/octet-stream"};if("text"in s&&typeof s.text=="string")return {...r,text:s.text};if("blob"in s&&typeof s.blob=="string"){let i=Uint8Array.from(atob(s.blob),a=>a.charCodeAt(0));return {...r,blob:i}}return r})}}log(e,t){if(this.app){let i={level:["debug","info","notice","warning","error","critical","alert","emergency"].includes(e)?e:"info",data:t,logger:"@mcp-apps-kit/ui"};try{this.app.sendLog(i);return}catch{}}({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[MCP Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),()=>this.hostContextHandlers.delete(e)}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}getHostCapabilities(){if(!this.app)return;let e=this.app.getHostCapabilities();if(!e)return;let t=e,s=this.app.getHostContext()?.availableDisplayModes;return {logging:t.logging,openLinks:t.openLinks,serverResources:t.serverResources,serverTools:t.serverTools,experimental:t.experimental,theming:{themes:["light","dark"]},displayModes:s?{modes:s}:void 0,statePersistence:{persistent:false},sizeNotifications:{},partialToolInput:{},appTools:{listChanged:false}}}getHostVersion(){if(!this.app)return;let e=this.app.getHostVersion();if(e)return {name:e.name,version:e.version}}async sendLog(e,t){if(!this.app)throw new d(u.NOT_CONNECTED,"MCP Apps adapter not connected");await this.app.sendLog({level:e,data:t,logger:"@mcp-apps-kit/ui"});}async sendSizeChanged(e){if(!this.app)throw new d(u.NOT_CONNECTED,"MCP Apps adapter not connected");await this.app.sendSizeChanged({width:e.width,height:e.height});}onToolInputPartial(e){return this.toolInputPartialHandlers.add(e),()=>this.toolInputPartialHandlers.delete(e)}setCallToolHandler(e){this.callToolHandler=e;}setListToolsHandler(e){this.listToolsHandler=e;}};var f=class{constructor(){this.connected=false;this.state=null;this.toolResultHandlers=new Set;this.toolInputHandlers=new Set;this.toolCancelledHandlers=new Set;this.hostContextHandlers=new Set;this.teardownHandlers=new Set;this.context=this.createDefaultContext();}createDefaultContext(){let e=typeof window<"u";return {theme:"light",displayMode:"inline",availableDisplayModes:["inline","fullscreen","pip"],viewport:{width:e?window.innerWidth:800,height:e?window.innerHeight:600},locale:e?navigator.language:"en-US",timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,platform:"web",deviceCapabilities:{touch:e?"ontouchstart"in window:false,hover:true}}}readContextFromSDK(){let e=this.getOpenAI();if(!e)return;let t=typeof window<"u";if(typeof e.theme=="string"&&(this.context.theme=e.theme),typeof e.displayMode=="string"&&(this.context.displayMode=e.displayMode),typeof e.locale=="string"&&(this.context.locale=e.locale),typeof e.userAgent=="string"&&Object.assign(this.context,{userAgent:e.userAgent}),typeof e.view=="string"&&(this.context.view=e.view),e.safeArea&&typeof e.safeArea=="object"){let n=e.safeArea;this.context.safeAreaInsets={top:typeof n.top=="number"?n.top:0,right:typeof n.right=="number"?n.right:0,bottom:typeof n.bottom=="number"?n.bottom:0,left:typeof n.left=="number"?n.left:0};}typeof e.maxHeight=="number"&&(this.context.viewport={width:t?window.innerWidth:800,height:e.maxHeight}),console.log("[OpenAI Adapter] Read context from SDK:",this.context);}notifyContextChange(){console.log(`[OpenAI Adapter] Notifying ${String(this.hostContextHandlers.size)} context change handlers`);let e={...this.context};for(let t of this.hostContextHandlers)t(e);}getOpenAI(){return typeof window<"u"&&"openai"in window?window.openai:null}async connect(){await this.waitForOpenAI();let e=this.getOpenAI();e&&(console.log("[OpenAI Adapter] Available SDK methods:",Object.keys(e)),this.readContextFromSDK(),typeof e.getToolOutput=="function"?(this.currentToolOutput=e.getToolOutput(),console.log("[OpenAI Adapter] Got tool output from SDK")):e.toolOutput?(this.currentToolOutput=e.toolOutput,console.log("[OpenAI Adapter] Got tool output from SDK property")):e.result&&(this.currentToolOutput=e.result,console.log("[OpenAI Adapter] Got result from SDK")),typeof e.getToolInput=="function"?this.currentToolInput=e.getToolInput():e.toolInput?this.currentToolInput=e.toolInput:e.input&&(this.currentToolInput=e.input),typeof e.init=="function"&&await e.init()),this.setupGlobalsListener(),this.connected=true;}setupGlobalsListener(){typeof window>"u"||(this.globalsHandler=e=>{let t=e.data;(t==="openai:set_globals"||typeof t=="object"&&t!==null&&"type"in t&&t.type==="openai:set_globals"||typeof t=="object"&&t!==null&&"message"in t&&t.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals event, refreshing context"),setTimeout(()=>{let s=this.context.theme,r=this.context.locale,i=this.context.displayMode;this.readContextFromSDK(),(this.context.theme!==s||this.context.locale!==r||this.context.displayMode!==i)&&(console.log("[OpenAI Adapter] Context changed, notifying handlers"),this.notifyContextChange());},10));},window.addEventListener("message",this.globalsHandler));}async waitForOpenAI(e=5e3){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai already available");return}return console.log("[OpenAI Adapter] Waiting for window.openai..."),new Promise(t=>{let n=Date.now(),s=false,r=()=>{s||(s=true,window.removeEventListener("message",a),t());},i=()=>{if(!s){if(this.getOpenAI()){console.log("[OpenAI Adapter] window.openai found via polling"),r();return}if(Date.now()-n>e){console.warn("[OpenAI Adapter] window.openai not found after timeout, proceeding anyway"),r();return}setTimeout(i,50);}},a=m=>{let l=m.data;(l==="openai:set_globals"||typeof l=="object"&&l!==null&&"type"in l&&l.type==="openai:set_globals"||typeof l=="object"&&l!==null&&"message"in l&&l.message==="openai:set_globals")&&(console.log("[OpenAI Adapter] Received set_globals message"),setTimeout(()=>{this.getOpenAI()?(console.log("[OpenAI Adapter] window.openai available after set_globals"),r()):console.log("[OpenAI Adapter] window.openai still not available after set_globals, continuing poll");},50));};window.addEventListener("message",a),i();})}isConnected(){return this.connected}async callTool(e,t){let n=this.getOpenAI();if(n&&typeof n.callTool=="function")return n.callTool(e,t);throw new Error("OpenAI SDK not available")}async sendMessage(e){let t=this.getOpenAI();t&&typeof t.sendMessage=="function"&&await t.sendMessage(e);}async openLink(e){let t=this.getOpenAI();t&&typeof t.openLink=="function"?await t.openLink(e):window.open(e,"_blank");}async requestDisplayMode(e){let t=this.getOpenAI();if(t&&typeof t.requestDisplayMode=="function"){let n=await t.requestDisplayMode({mode:e});return this.context={...this.context,displayMode:n.mode},this.notifyContextChange(),n}return this.context={...this.context,displayMode:e},this.notifyContextChange(),{mode:e}}requestClose(){let e=this.getOpenAI();e&&typeof e.close=="function"&&e.close();}getState(){return this.state}setState(e){this.state=e;let t=this.getOpenAI();t&&typeof t.setState=="function"&&t.setState(e);}async uploadFile(e){let t=this.getOpenAI();if(t&&typeof t.uploadFile=="function")return t.uploadFile(e);throw new Error("File upload not supported")}async getFileDownloadUrl(e){let t=this.getOpenAI();if(t&&typeof t.getFileDownloadUrl=="function")return t.getFileDownloadUrl(e);throw new Error("File download not supported")}async readResource(e){let t=this.getOpenAI();return t&&typeof t.readResource=="function"?t.readResource(e):{contents:[]}}log(e,t){({debug:console.debug,info:console.info,warning:console.warn,error:console.error}[e]??console.log)("[ChatGPT Apps]",t);}onToolResult(e){return this.toolResultHandlers.add(e),()=>this.toolResultHandlers.delete(e)}onToolInput(e){return this.toolInputHandlers.add(e),()=>this.toolInputHandlers.delete(e)}onToolCancelled(e){return this.toolCancelledHandlers.add(e),()=>this.toolCancelledHandlers.delete(e)}onHostContextChange(e){return this.hostContextHandlers.add(e),console.log(`[OpenAI Adapter] Host context handler added, total: ${String(this.hostContextHandlers.size)}`),()=>{this.hostContextHandlers.delete(e),console.log(`[OpenAI Adapter] Host context handler removed, total: ${String(this.hostContextHandlers.size)}`);}}onTeardown(e){return this.teardownHandlers.add(e),()=>this.teardownHandlers.delete(e)}getHostContext(){return this.context}getToolInput(){return this.currentToolInput}getToolOutput(){return this.currentToolOutput}getToolMeta(){return this.currentToolMeta}getHostCapabilities(){let e=this.getOpenAI(),t=e&&typeof e.uploadFile=="function",n=this.context.safeAreaInsets!==void 0,s=this.context.view!==void 0;return {openLinks:{},logging:{},theming:{themes:["light","dark"]},displayModes:{modes:["inline","fullscreen","pip"]},statePersistence:{persistent:false},fileUpload:t?{}:void 0,safeAreaInsets:n?{}:void 0,views:s?{}:void 0}}getHostVersion(){}async sendLog(e,t){let n={debug:"debug",info:"info",notice:"info",warning:"warning",error:"error",critical:"error",alert:"error",emergency:"error"};this.log(n[e],t);}async sendSizeChanged(e){let t=this.getOpenAI();t&&typeof t.notifyIntrinsicHeight=="function"&&t.notifyIntrinsicHeight(e.height);}onToolInputPartial(e){return this.log("debug","onToolInputPartial is not supported on ChatGPT"),()=>{}}setCallToolHandler(e){this.log("debug","setCallToolHandler is not supported on ChatGPT");}setListToolsHandler(e){this.log("debug","setListToolsHandler is not supported on ChatGPT");}};function U(){let o=window.location.href;if(o.includes("/api/apps/chatgpt/")||o.includes("chatgpt")||o.includes("sandbox-proxy")||o.includes("widget-content"))return true;let e=document.referrer;return !!(e.includes("chatgpt")||e.includes("openai.com"))}function y(){return typeof window>"u"?"mock":"openai"in window||U()?"openai":window.parent!==window?"mcp":"mock"}function C(o){return {async callTool(t,n){return await o.callTool(t,n)},async sendMessage(t){await o.sendMessage(t);},async sendFollowUpMessage(t){await o.sendMessage({type:"text",text:t});},async openLink(t){await o.openLink(t);},async requestDisplayMode(t){return o.requestDisplayMode(t)},requestClose(){o.requestClose();},getState(){return o.getState()},setState(t){o.setState(t);},...o.uploadFile&&{uploadFile:t=>{if(o.uploadFile)return o.uploadFile(t);throw new Error("uploadFile not supported")}},...o.getFileDownloadUrl&&{getFileDownloadUrl:t=>{if(o.getFileDownloadUrl)return o.getFileDownloadUrl(t);throw new Error("getFileDownloadUrl not supported")}},async readResource(t){return o.readResource(t)},log(t,n){o.log(t,n);},onToolResult(t){return o.onToolResult(t)},onToolInput(t){return o.onToolInput(t)},onToolCancelled(t){return o.onToolCancelled(t)},onHostContextChange(t){return o.onHostContextChange(t)},onTeardown(t){return o.onTeardown(t)},onToolInputPartial(t){return o.onToolInputPartial(t)},getHostCapabilities(){return o.getHostCapabilities()},getHostVersion(){return o.getHostVersion()},async sendLog(t,n){return o.sendLog(t,n)},async sendSizeChanged(t){return o.sendSizeChanged(t)},setupSizeChangedNotifications(){if(typeof window>"u"||typeof ResizeObserver>"u")return ()=>{};let t=new ResizeObserver(n=>{for(let s of n){let{width:r,height:i}=s.contentRect;o.sendSizeChanged({width:Math.round(r),height:Math.round(i)});}});return t.observe(document.body),()=>{t.disconnect();}},setCallToolHandler(t){o.setCallToolHandler(t);},setListToolsHandler(t){o.setListToolsHandler(t);},get hostContext(){return o.getHostContext()},get toolInput(){return o.getToolInput()},get toolOutput(){return o.getToolOutput()},get toolMeta(){return o.getToolMeta()}}}function z(o){switch(o){case "mcp":return new g;case "openai":return new f;case "mock":return new c;default:throw new Error(`Unknown adapter type: ${o}`)}}async function de(o){let e=o?.forceAdapter??y();if(!["mcp","openai","mock"].includes(e))throw new Error(`Unknown adapter type: ${e}`);let t=z(e);return await t.connect(),v.setAdapter(t),C(t)}export{h as ClientDebugLogger,L as LATEST_PROTOCOL_VERSION,g as McpAdapter,c as MockAdapter,f as OpenAIAdapter,D as RESOURCE_MIME_TYPE,F as RESOURCE_URI_META_KEY,d as UIError,u as UIErrorCode,x as applyDocumentTheme,b as applyHostFonts,k as applyHostStyleVariables,I as clearHostStyleVariables,v as clientDebugLogger,C as createAppsClient,de as createClient,y as detectProtocol,H as getDocumentTheme,A as removeHostFonts,M as safeSerialize,P as safeStringify,O as shouldLog};//# sourceMappingURL=index.js.map | ||
| //# sourceMappingURL=index.js.map |
+1
-1
| { | ||
| "name": "@mcp-apps-kit/ui", | ||
| "version": "0.2.3", | ||
| "version": "0.2.4", | ||
| "description": "Client-side SDK for MCP applications (vanilla JavaScript)", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+161
-54
@@ -5,12 +5,41 @@ # @mcp-apps-kit/ui | ||
| Client-side (UI/widget) SDK for MCP apps. | ||
| Client-side SDK for MCP applications (vanilla JavaScript). | ||
| Use this package inside the HTML/JS UI that your tool returns (a widget). It gives you a single `createClient()` API that **auto-detects the host** and lets you: | ||
| Use this inside the HTML/JS UI returned by your tools. The SDK auto-detects the host (MCP Apps or ChatGPT Apps) and exposes a unified client for tool calls and host context. | ||
| - call tools | ||
| - read tool results and tool inputs | ||
| - react to host context (theme, display mode, safe areas, etc.) | ||
| ## Table of Contents | ||
| This package is framework-agnostic (vanilla TS/JS). If you’re using React, prefer `@mcp-apps-kit/ui-react`. | ||
| - [Background](#background) | ||
| - [Features](#features) | ||
| - [Compatibility](#compatibility) | ||
| - [Install](#install) | ||
| - [Usage](#usage) | ||
| - [Debug Logging](#debug-logging) | ||
| - [Examples](#examples) | ||
| - [API](#api) | ||
| - [Contributing](#contributing) | ||
| - [License](#license) | ||
| ## Background | ||
| Widget UIs run inside host environments with different APIs and capabilities. This package normalizes those differences so your UI code can call tools, read results, and respond to host context changes from a single API. For React apps, use `@mcp-apps-kit/ui-react`. | ||
| ## Features | ||
| - `createClient()` with host auto-detection | ||
| - Tool calls with optional TypeScript typing | ||
| - Host context access (theme, display mode, safe areas) | ||
| - Tool inputs and results access | ||
| - Optional debug logger that transports logs via MCP | ||
| - Test adapter for local development | ||
| - **Host capabilities** - Query what the host supports (theming, display modes, file upload, etc.) | ||
| - **Bidirectional tools** - Register handlers for host-initiated tool calls | ||
| - **Theme & style utilities** - Apply host themes and CSS variables | ||
| ## Compatibility | ||
| - Hosts: MCP Apps and ChatGPT (OpenAI Apps SDK) | ||
| - Node.js: `>= 18` for tooling/builds (browser runtime) | ||
| - MCP SDK: uses `@modelcontextprotocol/ext-apps` | ||
| ## Install | ||
@@ -22,4 +51,6 @@ | ||
| ## Quick start | ||
| ## Usage | ||
| ### Quick start | ||
| ```ts | ||
@@ -30,6 +61,4 @@ import { createClient } from "@mcp-apps-kit/ui"; | ||
| // Call a tool by name | ||
| await client.callTool("greet", { name: "Alice" }); | ||
| // React to host context changes (theme, etc.) | ||
| client.onHostContextChange((ctx) => { | ||
@@ -40,6 +69,4 @@ document.documentElement.dataset.theme = ctx.theme; | ||
| ## Typed tool calls (recommended) | ||
| ### Typed tool calls | ||
| If your server exports tool types, you can parameterize the client to get fully typed `callTool()` inputs/outputs. | ||
| ```ts | ||
@@ -54,6 +81,4 @@ import { createClient } from "@mcp-apps-kit/ui"; | ||
| ## Testing locally | ||
| ### Local testing | ||
| You can force a specific adapter (useful in local dev / unit tests): | ||
| ```ts | ||
@@ -67,67 +92,149 @@ import { createClient } from "@mcp-apps-kit/ui"; | ||
| The client debug logger allows you to send structured logs from your UI to the server through the MCP protocol. This bypasses sandbox restrictions in iframe environments where `console` access may be unavailable (e.g., mobile ChatGPT). | ||
| Send structured logs from the UI to the server via MCP: | ||
| ### Basic Usage | ||
| ```ts | ||
| import { clientDebugLogger } from "@mcp-apps-kit/ui"; | ||
| // Configure the logger (call once at app startup) | ||
| clientDebugLogger.configure({ | ||
| enabled: true, // Enable MCP transport | ||
| level: "debug", // Minimum level to log | ||
| source: "my-widget", // Identifier for log entries | ||
| enabled: true, | ||
| level: "debug", | ||
| source: "my-widget", | ||
| }); | ||
| // Log messages at different levels | ||
| clientDebugLogger.debug("Component mounted", { props }); | ||
| clientDebugLogger.info("User action", { action: "click", target: "button" }); | ||
| clientDebugLogger.warn("Validation warning", { field: "email" }); | ||
| clientDebugLogger.error("API request failed", { error: err.message }); | ||
| clientDebugLogger.info("Component mounted", { props: "..." }); | ||
| ``` | ||
| ### Features | ||
| Server-side configuration: | ||
| - **Intelligent batching**: Logs are batched to reduce MCP calls (default: 10 entries or 5 seconds) | ||
| - **Immediate flush on errors**: Error-level logs are flushed immediately | ||
| - **Automatic fallback**: Falls back to `console` when MCP transport is unavailable | ||
| - **Circular reference handling**: Safely serializes objects with circular references | ||
| - **Graceful degradation**: Works silently in restricted environments | ||
| ```ts | ||
| const app = createApp({ | ||
| config: { | ||
| debug: { | ||
| logTool: true, | ||
| level: "debug", | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
| ### Configuration Options | ||
| ## Examples | ||
| - `../../examples/minimal` | ||
| - [kanban-mcp-example](https://github.com/AndurilCode/kanban-mcp-example) | ||
| ## API | ||
| ### Client Factory | ||
| - `createClient(options?)` - Create a connected client with auto-detection | ||
| - `detectProtocol()` - Detect the host platform ("mcp" | "openai" | "mock") | ||
| ### Host Capabilities | ||
| ```ts | ||
| clientDebugLogger.configure({ | ||
| enabled: true, // Enable/disable MCP transport | ||
| level: "info", // "debug" | "info" | "warn" | "error" | ||
| batchSize: 10, // Flush after N log entries | ||
| flushIntervalMs: 5000, // Max time between flushes (ms) | ||
| source: "my-app", // Source identifier for logs | ||
| }); | ||
| const capabilities = client.getHostCapabilities(); | ||
| // Common capabilities (both platforms) | ||
| capabilities?.theming?.themes; // ["light", "dark"] | ||
| capabilities?.displayModes?.modes; // ["inline", "fullscreen", "pip"] | ||
| capabilities?.statePersistence?.persistent; // boolean | ||
| capabilities?.openLinks; // {} if supported | ||
| capabilities?.logging; // {} if supported | ||
| // MCP Apps specific | ||
| capabilities?.serverTools?.listChanged; // boolean | ||
| capabilities?.serverResources?.listChanged; // boolean | ||
| capabilities?.sizeNotifications; // {} if supported | ||
| capabilities?.partialToolInput; // {} if supported | ||
| // ChatGPT specific | ||
| capabilities?.fileUpload; // {} if supported | ||
| capabilities?.safeAreaInsets; // {} if supported | ||
| capabilities?.views; // {} if supported | ||
| ``` | ||
| ### Server-Side Setup | ||
| ### Host Version | ||
| For the logs to be received, the server must have debug logging enabled: | ||
| ```ts | ||
| const version = client.getHostVersion(); | ||
| // { name: "Claude Desktop", version: "1.0.0" } (MCP Apps only) | ||
| ``` | ||
| ### Theme & Style Utilities | ||
| ```ts | ||
| // server/index.ts | ||
| const app = createApp({ | ||
| config: { | ||
| debug: { enabled: true, level: "debug" }, | ||
| }, | ||
| import { | ||
| applyDocumentTheme, | ||
| getDocumentTheme, | ||
| applyHostStyleVariables, | ||
| applyHostFonts, | ||
| removeHostFonts, | ||
| clearHostStyleVariables, | ||
| } from "@mcp-apps-kit/ui"; | ||
| // Apply theme to document | ||
| applyDocumentTheme("dark"); // or "light" or "os" | ||
| // Apply host-provided CSS variables | ||
| applyHostStyleVariables({ | ||
| "primary-color": "#007bff", | ||
| "--font-size": "16px", | ||
| }); | ||
| // Apply host-provided font CSS | ||
| applyHostFonts("@font-face { ... }"); | ||
| ``` | ||
| **See also:** [@mcp-apps-kit/core README](../core/README.md) for server-side configuration. | ||
| ### Bidirectional Tools (MCP Apps) | ||
| ## Documentation & examples | ||
| ```ts | ||
| // Register a handler for host-initiated tool calls | ||
| client.setCallToolHandler(async (toolName, args) => { | ||
| if (toolName === "get_selection") { | ||
| return { selection: document.getSelection()?.toString() }; | ||
| } | ||
| throw new Error(`Unknown tool: ${toolName}`); | ||
| }); | ||
| - Project overview: ../../README.md | ||
| - Examples that include UI code: | ||
| - [kanban-mcp-example](https://github.com/AndurilCode/kanban-mcp-example) | ||
| - ../../examples/minimal | ||
| // Register a handler for listing available tools | ||
| client.setListToolsHandler(async () => [ | ||
| { name: "get_selection", description: "Get current text selection" }, | ||
| ]); | ||
| ``` | ||
| ### Protocol Logging | ||
| ```ts | ||
| // Send logs via the MCP protocol (appears in host logs) | ||
| await client.sendLog("info", { event: "user_action", details: "..." }); | ||
| ``` | ||
| ### Error Handling | ||
| ```ts | ||
| import { UIError, UIErrorCode } from "@mcp-apps-kit/ui"; | ||
| try { | ||
| await client.callTool("unknown"); | ||
| } catch (error) { | ||
| if (error instanceof UIError) { | ||
| console.error(error.code, error.message); | ||
| } | ||
| } | ||
| ``` | ||
| ### Key Types | ||
| - `HostContext` - Theme, viewport, locale, display mode, etc. | ||
| - `HostCapabilities` - Protocol-agnostic capability interface | ||
| - `HostVersion` - Host application name and version | ||
| - `AppsClient` - Main client interface | ||
| - `UIError`, `UIErrorCode` - Client-side error types | ||
| ## Contributing | ||
| See `../../CONTRIBUTING.md` for development setup and guidelines. Issues and pull requests are welcome. | ||
| ## License | ||
| MIT |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
398597
40.18%1604
43.47%235
83.59%3
200%