@mcp-b/mcp-iframe 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -90,4 +90,4 @@ declare global {
90
90
  declare function registerMCPIframeElement(tagName?: string): void;
91
91
  //#endregion
92
92
  export { registerMCPIframeElement as a, MCPIframeItemsEventDetail as i, MCPIframeErrorEventDetail as n, MCPIframeEventMap as r, MCPIframeElement as t };
93
- //# sourceMappingURL=MCPIframeElement-d12Xcjs_.d.ts.map
93
+ //# sourceMappingURL=MCPIframeElement-Br8JNWm_.d.ts.map
@@ -1,2 +1,2 @@
1
1
  import{DEFAULT_IFRAME_CHANNEL_ID as e,IframeParentTransport as t}from"@mcp-b/transports";import{Client as n,UriTemplate as r}from"@modelcontextprotocol/client";const i=3e4,a=()=>({tools:[],resources:[],resourceTemplates:[],prompts:[]});function o(e){return`registerResource`in e&&typeof e.registerResource==`function`&&`registerPrompt`in e&&typeof e.registerPrompt==`function`}function s(e){return`syncNativeTools`in e&&typeof e.syncNativeTools==`function`}function c(e){return e.replace(/[^a-zA-Z0-9_.-]/g,`_`)}function l(e,t,n=[]){let r=new URL(`mcp-iframe:`);return r.searchParams.set(`source`,e),r.searchParams.set(`uri`,t),[...new Set(n)].reduce((e,t,n)=>`${e}&variable-${n}={${t}*}`,r.href)}function u(e,t,n){return e.has(t)?(console.warn(`[MCPIframe] Ignoring duplicate iframe ${n} "${t}"`),!0):!1}function d(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Array.isArray(t)?t.map(decodeURIComponent):decodeURIComponent(t)]))}const f=[`src`,`srcdoc`,`name`,`sandbox`,`allow`,`allowfullscreen`,`width`,`height`,`loading`,`referrerpolicy`,`credentialless`];var p=class extends HTMLElement{#e=null;#t=null;#n=null;#r=0;#i=!1;static get observedAttributes(){return[...f,`id`,`target-origin`,`channel`,`call-timeout`,`prefix-separator`]}constructor(){super(),this.attachShadow({mode:`open`})}connectedCallback(){this.#e?this.#D():this.#a()}disconnectedCallback(){++this.#r,this.#O()}attributeChangedCallback(e,t,n){if(t!==n){if(e===`target-origin`||e===`channel`){this.#e&&this.isConnected&&this.#D();return}if(e===`call-timeout`){let e=Number(n);n!==null&&(!Number.isSafeInteger(e)||e<=0)&&console.warn(`[MCPIframe] Invalid call-timeout "${n}". Using ${i}.`);return}if(e===`id`||e===`prefix-separator`){if(e===`prefix-separator`&&n!==null){let e=c(n);e!==n&&console.warn(`[MCPIframe] Invalid prefix-separator "${n}". Using "${e}".`)}let t=this.#t;t&&this.#u(t,`Failed to update parent registrations`);return}if(!(!this.#e||!f.includes(e))){if(n===null?this.#e.removeAttribute(e):this.#e.setAttribute(e,n),e===`src`||e===`srcdoc`)++this.#r,this.#O();else if(e===`name`){let e=this.#t;e&&this.#u(e,`Failed to update parent registrations`)}}}}get iframe(){return this.#e}get ready(){return this.#t?.ready??!1}get exposedTools(){return Array.from(this.#t?.toolRegistrations.keys()??[])}get exposedResources(){return Array.from(this.#t?.resourceRegistrations.keys()??[])}get exposedPrompts(){return Array.from(this.#t?.promptRegistrations.keys()??[])}get itemPrefix(){return`${c(this.id||this.getAttribute(`name`)||`iframe`)}${c(this.getAttribute(`prefix-separator`)??`_`)}`}async refresh(){let e=this.#t;if(!e?.ready)throw Error(`Not connected to iframe MCP server`);if(await this.#d(e,!0,`Failed to refresh iframe items`),await this.#f(e),!this.#l(e)||!e.ready)throw Error(`Iframe connection changed before refresh completed`)}#a(){if(!this.#e){this.#e=document.createElement(`iframe`);for(let e of f){let t=this.getAttribute(e);t!==null&&this.#e.setAttribute(e,t)}this.#e.style.border=`none`,this.#e.addEventListener(`load`,()=>void this.#D()),this.shadowRoot?.appendChild(this.#e)}}async#o(e){let t=this.#n;t&&await t.catch(()=>void 0);let n=this.#e;if(e!==this.#r||!n||!this.isConnected)return;let r=this.#s(e,n);this.#n=r;try{await r}finally{this.#n===r&&(this.#n=null)}}async#s(r,i){let o;try{let s=new t({iframe:i,targetOrigin:this.#g(),channelId:this.getAttribute(`channel`)??e}),c={autoRefresh:!1,debounceMs:0,onChanged:()=>{o&&this.#u(o,`Failed to refresh iframe items`)}},l=new n({name:`MCPIframe:${this.id||`anonymous`}`,version:`1.0.0`},{versionNegotiation:{mode:`auto`},listChanged:{tools:c,resources:c,prompts:c}}),u={client:l,ready:!1,refreshRevision:0,refreshQueue:Promise.resolve(),items:a(),toolRegistrations:new Map,resourceRegistrations:new Map,promptRegistrations:new Map};if(o=u,this.#t=u,l.onclose=()=>{u.ready&&this.#O(u)},l.onerror=e=>{this.#h(u,e,`Iframe MCP client error`)},await l.connect(s),r!==this.#r||!this.#l(u)||(await this.#d(u,!1,`Failed to connect`),await this.#f(u),!this.#l(u)))return;u.ready=!0,this.#p(`mcp-iframe-ready`)}catch(e){if(r!==this.#r||!this.isConnected||o&&!this.#l(o))return;o?this.#h(o,e,`Failed to connect`):this.#m(e,`Failed to connect`)}}async#c(e){let t=e.getServerCapabilities(),[n,r,i,a]=await Promise.all([t?.tools?e.listTools(void 0,{cacheMode:`refresh`}).then(e=>e.tools):[],t?.resources?e.listResources(void 0,{cacheMode:`refresh`}).then(e=>e.resources):[],t?.resources?e.listResourceTemplates(void 0,{cacheMode:`refresh`}).then(e=>e.resourceTemplates):[],t?.prompts?e.listPrompts(void 0,{cacheMode:`refresh`}).then(e=>e.prompts):[]]);return{tools:n,resources:r,resourceTemplates:i,prompts:a}}#l(e){return this.#t===e}#u(e,t){this.#d(e,!0,t).catch(()=>void 0)}#d(e,t,n){let r=++e.refreshRevision,i=!1,a=e.refreshQueue.catch(()=>void 0).then(async()=>{let a=()=>this.#l(e)&&r===e.refreshRevision;if(a()){try{let t=await this.#c(e.client);if(!a())return;this.#x(e),i=!0,e.items=t,await this.#_(e,this.itemPrefix,a)}catch(t){if(!a()){i&&this.#x(e);return}throw this.#h(e,t,n),t}if(!a()){this.#x(e);return}t&&e.ready&&this.#p(`mcp-iframe-items-changed`)}});return e.refreshQueue=a,a}async#f(e){for(;this.#l(e);){let t=e.refreshQueue;if(await t,t===e.refreshQueue)return}}#p(e){this.dispatchEvent(new CustomEvent(e,{detail:{tools:this.exposedTools,resources:this.exposedResources,prompts:this.exposedPrompts}}))}#m(e,t){console.error(`[MCPIframe] ${t}:`,e),this.dispatchEvent(new CustomEvent(`mcp-iframe-error`,{detail:{error:e}}))}#h(e,t,n){this.#k(e)&&(this.#m(t,n),this.#A(e))}#g(){let e=this.getAttribute(`target-origin`);if(e!==null){if(!e)throw Error(`target-origin cannot be empty`);return e}if(this.#e?.hasAttribute(`sandbox`)&&!this.#e.sandbox.contains(`allow-same-origin`))throw Error(`Opaque sandboxed iframes require target-origin="*"`);if(this.hasAttribute(`srcdoc`))return window.location.origin;let t=this.getAttribute(`src`);if(!t)return window.location.origin;let n=new URL(t,window.location.href);if(n.protocol===`about:`)return window.location.origin;if(n.origin===`null`)throw Error(`Opaque iframe sources require target-origin="*"`);return n.origin}async#_(e,t,n){let r=document.modelContext??navigator.modelContext;if(!r)throw Error(`Model Context API not available on parent`);if(this.#i&&s(r)){if(await r.syncNativeTools(),!n())return;this.#i=!1}await this.#v(e,r,t,n),n()&&(o(r)?(this.#y(e,r,t),this.#b(e,r,t)):(e.items.resources.length>0||e.items.resourceTemplates.length>0||e.items.prompts.length>0)&&console.warn(`[MCPIframe] Parent modelContext does not provide the MCP-B resource and prompt extensions`))}async#v(e,t,n,r){for(let i of e.items.tools){if(!r())return;let a=`${n}${i.name}`;if(u(e.toolRegistrations,a,`tool`))continue;let o={name:a,...i.title!==void 0&&{title:i.title},description:i.description??`Tool from iframe: ${i.name}`,inputSchema:i.inputSchema,...i.annotations?.readOnlyHint!==void 0&&{annotations:{readOnlyHint:i.annotations.readOnlyHint}},execute:e=>this.#w(i.name,e)},s=new AbortController;e.toolRegistrations.set(a,s);try{await t.registerTool(o,{signal:s.signal})}catch(t){let n=s.signal.aborted;if(n||(this.#i=!0,s.abort()),e.toolRegistrations.get(a)===s&&e.toolRegistrations.delete(a),!n)throw t}}}#y(e,t,n){for(let r of e.items.resources){let i=l(n,r.uri);if(u(e.resourceRegistrations,i,`resource`))continue;let a={uri:i,name:r.name,...r.description!==void 0&&{description:r.description},...r.mimeType!==void 0&&{mimeType:r.mimeType},read:(e,t)=>this.#T(r.uri)},o=t.registerResource(a);e.resourceRegistrations.set(i,o)}for(let i of e.items.resourceTemplates){let a=new r(i.uriTemplate),o=l(n,i.uriTemplate,a.variableNames);if(u(e.resourceRegistrations,o,`resource`))continue;let s={uri:o,name:i.name,...i.description!==void 0&&{description:i.description},...i.mimeType!==void 0&&{mimeType:i.mimeType},read:(e,t)=>this.#T(a.expand(d(t??{})))},c=t.registerResource(s);e.resourceRegistrations.set(o,c)}}#b(e,t,n){for(let r of e.items.prompts){let i=`${n}${r.name}`;if(u(e.promptRegistrations,i,`prompt`))continue;let a={name:i,...r.description!==void 0&&{description:r.description},...r.arguments&&r.arguments.length>0&&{argsSchema:{type:`object`,properties:Object.fromEntries(r.arguments.map(e=>[e.name,{type:`string`,...e.description!==void 0&&{description:e.description}}])),required:r.arguments.filter(e=>e.required).map(e=>e.name)}},get:e=>this.#E(r.name,e)},o=t.registerPrompt(a);e.promptRegistrations.set(i,o)}}#x(e){let t=[...e.toolRegistrations.values()],n=[...e.resourceRegistrations.values(),...e.promptRegistrations.values()];e.toolRegistrations.clear(),e.resourceRegistrations.clear(),e.promptRegistrations.clear(),e.items=a(),t.length>0&&(this.#i=!0);for(let e of t)try{e.abort()}catch(e){console.warn(`[MCPIframe] Failed to unregister a parent tool:`,e)}for(let e of n)try{e.unregister()}catch(e){console.warn(`[MCPIframe] Failed to unregister a parent item:`,e)}}#S(){let e=this.#t;if(!e?.ready)throw Error(`Not connected to iframe MCP server`);return e.client}#C(){let e=Number(this.getAttribute(`call-timeout`));return Number.isSafeInteger(e)&&e>0?e:i}async#w(e,t){return this.#S().callTool({name:e,arguments:t},{timeout:this.#C()})}async#T(e){return this.#S().readResource({uri:e},{timeout:this.#C()})}async#E(e,t){return this.#S().getPrompt({name:e,arguments:t},{timeout:this.#C()})}async#D(){let e=++this.#r;await this.#O(),!(e!==this.#r||!this.isConnected)&&await this.#o(e)}async#O(e=this.#t){!e||!this.#k(e)||await this.#A(e)}#k(e){return this.#l(e)?(this.#t=null,++e.refreshRevision,e.ready=!1,delete e.client.onclose,delete e.client.onerror,this.#x(e),!0):!1}async#A(e){try{await e.client.close()}catch(e){console.warn(`[MCPIframeElement] Error closing client during disconnect:`,e)}}};function m(e=`mcp-iframe`){typeof customElements<`u`&&!customElements.get(e)&&customElements.define(e,p)}export{m as n,p as t};
2
- //# sourceMappingURL=MCPIframeElement-BbBz_xpV.js.map
2
+ //# sourceMappingURL=MCPIframeElement-CYns0bdY.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MCPIframeElement-BbBz_xpV.js","names":["#iframe","#reconnect","#createIframe","#connectionRequestGeneration","#disconnect","#connection","#requestRefresh","#queueRefresh","#waitForRefreshQueue","#isCurrentConnection","#connect","#connectionAttempt","#connectCurrent","#getTargetOrigin","#failConnection","#dispatchItems","#dispatchError","#fetchAllFromIframe","#unregisterAll","#registerAllOnModelContext","#invalidateConnection","#closeConnection","#nativeToolSyncPending","#registerToolsOnModelContext","#registerResourcesOnModelContext","#registerPromptsOnModelContext","#callIframeTool","#readIframeResource","#getIframePrompt","#requireClient","#getCallTimeout"],"sources":["../src/MCPIframeElement.ts"],"sourcesContent":["/**\n * MCPIframe Custom Element\n *\n * A custom element that wraps an iframe and automatically exposes tools,\n * resources, and prompts registered in the iframe's MCP server to the\n * parent page's Model Context API.\n *\n * The iframe should expose its MCP server through `document.modelContext`.\n * Older runtimes that only expose `navigator.modelContext` remain supported.\n *\n * @example\n * ```html\n * <mcp-iframe src=\"./child-app.html\" id=\"my-app\"></mcp-iframe>\n * ```\n *\n * Tool and prompt names use the element's ID as a prefix. Resources use a wrapper URI:\n * - Child registers tool \"calculate\" -> Parent sees \"my-app_calculate\"\n * - Child registers resource \"config://settings\" -> Parent sees an \"mcp-iframe:\" wrapper URI\n * - Child registers prompt \"help\" -> Parent sees \"my-app_help\"\n *\n * Note: The prefix separator defaults to underscore (_) to ensure WebMCP compatibility.\n * The parent model context validates the final prefixed tool name.\n *\n * @example\n * ```typescript\n * const mcpIframe = document.querySelector('mcp-iframe');\n * mcpIframe.addEventListener('mcp-iframe-ready', (e) => {\n * console.log('Tools:', e.detail.tools);\n * console.log('Resources:', e.detail.resources);\n * console.log('Prompts:', e.detail.prompts);\n * });\n * ```\n */\n\nimport { DEFAULT_IFRAME_CHANNEL_ID, IframeParentTransport } from '@mcp-b/transports';\nimport {\n type BrowserMcpServer,\n type PromptDescriptor,\n type ResourceDescriptor,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type {\n CallToolResult,\n InputSchema,\n ModelContext,\n ModelContextTool,\n RegistrationHandle,\n} from '@mcp-b/webmcp-types';\nimport {\n Client,\n UriTemplate,\n type GetPromptResult,\n type Prompt,\n type ReadResourceResult,\n type Resource,\n type ResourceTemplateType,\n type Tool,\n type Variables,\n} from '@modelcontextprotocol/client';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nconst DEFAULT_CALL_TIMEOUT = 30000;\nconst DEFAULT_PREFIX_SEPARATOR = '_';\n\ntype McpBRegistrationExtensions = Pick<BrowserMcpServer, 'registerPrompt' | 'registerResource'>;\ntype NativeToolSyncExtension = Pick<BrowserMcpServer, 'syncNativeTools'>;\n\ninterface McpItems {\n tools: Tool[];\n resources: Resource[];\n resourceTemplates: ResourceTemplateType[];\n prompts: Prompt[];\n}\n\ninterface Connection {\n client: Client;\n ready: boolean;\n refreshRevision: number;\n refreshQueue: Promise<void>;\n items: McpItems;\n toolRegistrations: Map<string, AbortController>;\n resourceRegistrations: Map<string, RegistrationHandle>;\n promptRegistrations: Map<string, RegistrationHandle>;\n}\n\nconst emptyItems = (): McpItems => ({\n tools: [],\n resources: [],\n resourceTemplates: [],\n prompts: [],\n});\n\nfunction hasMcpBRegistrationExtensions(\n modelContext: ModelContext\n): modelContext is ModelContext & McpBRegistrationExtensions {\n return (\n 'registerResource' in modelContext &&\n typeof modelContext.registerResource === 'function' &&\n 'registerPrompt' in modelContext &&\n typeof modelContext.registerPrompt === 'function'\n );\n}\n\nfunction hasNativeToolSync(\n modelContext: ModelContext\n): modelContext is ModelContext & NativeToolSyncExtension {\n return 'syncNativeTools' in modelContext && typeof modelContext.syncNativeTools === 'function';\n}\n\n/**\n * Sanitizes a string to contain only valid MCP name characters.\n * Replaces invalid characters with underscores.\n */\nfunction sanitizeMCPNamePart(str: string): string {\n return str.replace(/[^a-zA-Z0-9_.-]/g, '_');\n}\n\nfunction createParentResourceUri(\n source: string,\n childUri: string,\n variables: readonly string[] = []\n): string {\n const parentUri = new URL('mcp-iframe:');\n parentUri.searchParams.set('source', source);\n parentUri.searchParams.set('uri', childUri);\n return [...new Set(variables)].reduce(\n (uri, variable, index) => `${uri}&variable-${index}={${variable}*}`,\n parentUri.href\n );\n}\n\n/**\n * Registration maps are keyed by the parent-visible name or URI, so a second item with the same\n * key can only shadow a live registration that `#unregisterAll` would then never tear down.\n */\nfunction isDuplicateRegistration(\n registrations: ReadonlyMap<string, unknown>,\n key: string,\n kind: string\n): boolean {\n if (!registrations.has(key)) return false;\n console.warn(`[MCPIframe] Ignoring duplicate iframe ${kind} \"${key}\"`);\n return true;\n}\n\nfunction decodeTemplateVariables(variables: Variables): Variables {\n return Object.fromEntries(\n Object.entries(variables).map(([name, value]) => [\n name,\n Array.isArray(value) ? value.map(decodeURIComponent) : decodeURIComponent(value),\n ])\n );\n}\n\n/** Standard iframe attributes that are mirrored to the internal iframe */\nconst IFRAME_ATTRIBUTES = [\n 'src',\n 'srcdoc',\n 'name',\n 'sandbox',\n 'allow',\n 'allowfullscreen',\n 'width',\n 'height',\n 'loading',\n 'referrerpolicy',\n 'credentialless',\n] satisfies readonly string[];\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Names of items currently exposed on the parent model context. */\nexport interface MCPIframeItemsEventDetail {\n tools: string[];\n resources: string[];\n prompts: string[];\n}\n\n/** Custom event detail for mcp-iframe-error */\nexport interface MCPIframeErrorEventDetail {\n error: unknown;\n}\n\nexport interface MCPIframeEventMap {\n 'mcp-iframe-ready': CustomEvent<MCPIframeItemsEventDetail>;\n 'mcp-iframe-error': CustomEvent<MCPIframeErrorEventDetail>;\n 'mcp-iframe-items-changed': CustomEvent<MCPIframeItemsEventDetail>;\n}\n\n// ============================================================================\n// MCPIframeElement\n// ============================================================================\n\n/**\n * MCPIframe Custom Element\n *\n * Wraps an iframe and exposes its MCP tools, resources, and prompts\n * to the parent's Model Context API.\n *\n * @fires mcp-iframe-ready - When connected to iframe's MCP server\n * @fires mcp-iframe-error - When the connection or an item refresh fails\n * @fires mcp-iframe-items-changed - When items are refreshed\n */\nexport class MCPIframeElement extends HTMLElement {\n declare addEventListener: (<K extends keyof MCPIframeEventMap>(\n type: K,\n listener: (this: MCPIframeElement, event: MCPIframeEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions\n ) => void) &\n HTMLElement['addEventListener'];\n\n declare removeEventListener: (<K extends keyof MCPIframeEventMap>(\n type: K,\n listener: (this: MCPIframeElement, event: MCPIframeEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions\n ) => void) &\n HTMLElement['removeEventListener'];\n\n #iframe: HTMLIFrameElement | null = null;\n #connection: Connection | null = null;\n #connectionAttempt: Promise<void> | null = null;\n #connectionRequestGeneration = 0;\n #nativeToolSyncPending = false;\n\n static get observedAttributes(): string[] {\n return [\n ...IFRAME_ATTRIBUTES,\n 'id',\n 'target-origin',\n 'channel',\n 'call-timeout',\n 'prefix-separator',\n ];\n }\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n\n // ==================== Lifecycle ====================\n\n connectedCallback(): void {\n if (this.#iframe) {\n void this.#reconnect();\n } else {\n this.#createIframe();\n }\n }\n\n disconnectedCallback(): void {\n ++this.#connectionRequestGeneration;\n void this.#disconnect();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'target-origin' || name === 'channel') {\n if (this.#iframe && this.isConnected) void this.#reconnect();\n return;\n }\n\n if (name === 'call-timeout') {\n const timeout = Number(newValue);\n if (newValue !== null && (!Number.isSafeInteger(timeout) || timeout <= 0)) {\n console.warn(\n `[MCPIframe] Invalid call-timeout \"${newValue}\". Using ${DEFAULT_CALL_TIMEOUT}.`\n );\n }\n return;\n }\n\n if (name === 'id' || name === 'prefix-separator') {\n if (name === 'prefix-separator' && newValue !== null) {\n const sanitized = sanitizeMCPNamePart(newValue);\n if (sanitized !== newValue) {\n console.warn(`[MCPIframe] Invalid prefix-separator \"${newValue}\". Using \"${sanitized}\".`);\n }\n }\n const connection = this.#connection;\n if (connection) {\n this.#requestRefresh(connection, 'Failed to update parent registrations');\n }\n return;\n }\n\n if (!this.#iframe || !IFRAME_ATTRIBUTES.includes(name)) return;\n if (newValue === null) {\n this.#iframe.removeAttribute(name);\n } else {\n this.#iframe.setAttribute(name, newValue);\n }\n if (name === 'src' || name === 'srcdoc') {\n ++this.#connectionRequestGeneration;\n void this.#disconnect();\n } else if (name === 'name') {\n const connection = this.#connection;\n if (connection) {\n this.#requestRefresh(connection, 'Failed to update parent registrations');\n }\n }\n }\n\n // ==================== Public API ====================\n\n /** The wrapped iframe element */\n get iframe(): HTMLIFrameElement | null {\n return this.#iframe;\n }\n\n /** Whether the element is connected to the iframe's MCP server */\n get ready(): boolean {\n return this.#connection?.ready ?? false;\n }\n\n /** List of exposed tool names (with prefix) */\n get exposedTools(): string[] {\n return Array.from(this.#connection?.toolRegistrations.keys() ?? []);\n }\n\n /** List of exposed parent-side resource wrapper URIs */\n get exposedResources(): string[] {\n return Array.from(this.#connection?.resourceRegistrations.keys() ?? []);\n }\n\n /** List of exposed prompt names (with prefix) */\n get exposedPrompts(): string[] {\n return Array.from(this.#connection?.promptRegistrations.keys() ?? []);\n }\n\n /** The item name prefix (id + separator), sanitized for MCP compatibility */\n get itemPrefix(): string {\n const rawId = this.id || this.getAttribute('name') || 'iframe';\n const id = sanitizeMCPNamePart(rawId);\n const separator = sanitizeMCPNamePart(\n this.getAttribute('prefix-separator') ?? DEFAULT_PREFIX_SEPARATOR\n );\n return `${id}${separator}`;\n }\n\n /** Manually refresh all items from the iframe */\n async refresh(): Promise<void> {\n const connection = this.#connection;\n if (!connection?.ready) {\n throw new Error('Not connected to iframe MCP server');\n }\n\n await this.#queueRefresh(connection, true, 'Failed to refresh iframe items');\n await this.#waitForRefreshQueue(connection);\n if (!this.#isCurrentConnection(connection) || !connection.ready) {\n throw new Error('Iframe connection changed before refresh completed');\n }\n }\n\n // ==================== Private Methods ====================\n\n #createIframe(): void {\n if (this.#iframe) return;\n\n this.#iframe = document.createElement('iframe');\n\n // Mirror all iframe attributes\n for (const attr of IFRAME_ATTRIBUTES) {\n const value = this.getAttribute(attr);\n if (value !== null) {\n this.#iframe.setAttribute(attr, value);\n }\n }\n\n this.#iframe.style.border = 'none';\n\n // src/srcdoc changes only tear down; the load event rebuilds the connection.\n this.#iframe.addEventListener('load', () => void this.#reconnect());\n\n this.shadowRoot?.appendChild(this.#iframe);\n }\n\n async #connect(requestGeneration: number): Promise<void> {\n const activeAttempt = this.#connectionAttempt;\n if (activeAttempt) {\n await activeAttempt.catch(() => undefined);\n }\n const iframe = this.#iframe;\n if (requestGeneration !== this.#connectionRequestGeneration || !iframe || !this.isConnected) {\n return;\n }\n\n const attempt = this.#connectCurrent(requestGeneration, iframe);\n this.#connectionAttempt = attempt;\n try {\n await attempt;\n } finally {\n if (this.#connectionAttempt === attempt) {\n this.#connectionAttempt = null;\n }\n }\n }\n\n async #connectCurrent(requestGeneration: number, iframe: HTMLIFrameElement): Promise<void> {\n let connection: Connection | undefined;\n\n try {\n const transport = new IframeParentTransport({\n iframe,\n targetOrigin: this.#getTargetOrigin(),\n channelId: this.getAttribute('channel') ?? DEFAULT_IFRAME_CHANNEL_ID,\n });\n const onListChanged = () => {\n if (connection) this.#requestRefresh(connection, 'Failed to refresh iframe items');\n };\n const listChanged = { autoRefresh: false, debounceMs: 0, onChanged: onListChanged };\n const client = new Client(\n { name: `MCPIframe:${this.id || 'anonymous'}`, version: '1.0.0' },\n {\n versionNegotiation: { mode: 'auto' },\n listChanged: { tools: listChanged, resources: listChanged, prompts: listChanged },\n }\n );\n const currentConnection: Connection = {\n client,\n ready: false,\n refreshRevision: 0,\n refreshQueue: Promise.resolve(),\n items: emptyItems(),\n toolRegistrations: new Map(),\n resourceRegistrations: new Map(),\n promptRegistrations: new Map(),\n };\n connection = currentConnection;\n this.#connection = currentConnection;\n client.onclose = () => {\n if (currentConnection.ready) void this.#disconnect(currentConnection);\n };\n client.onerror = (error) => {\n this.#failConnection(currentConnection, error, 'Iframe MCP client error');\n };\n\n await client.connect(transport);\n if (\n requestGeneration !== this.#connectionRequestGeneration ||\n !this.#isCurrentConnection(currentConnection)\n ) {\n return;\n }\n\n await this.#queueRefresh(currentConnection, false, 'Failed to connect');\n await this.#waitForRefreshQueue(currentConnection);\n if (!this.#isCurrentConnection(currentConnection)) return;\n currentConnection.ready = true;\n this.#dispatchItems('mcp-iframe-ready');\n } catch (error) {\n if (\n requestGeneration !== this.#connectionRequestGeneration ||\n !this.isConnected ||\n (connection && !this.#isCurrentConnection(connection))\n ) {\n return;\n }\n if (connection) {\n this.#failConnection(connection, error, 'Failed to connect');\n } else {\n this.#dispatchError(error, 'Failed to connect');\n }\n }\n }\n\n async #fetchAllFromIframe(client: Client): Promise<McpItems> {\n const capabilities = client.getServerCapabilities();\n const [tools, resources, resourceTemplates, prompts] = await Promise.all([\n capabilities?.tools\n ? client.listTools(undefined, { cacheMode: 'refresh' }).then((result) => result.tools)\n : [],\n capabilities?.resources\n ? client\n .listResources(undefined, { cacheMode: 'refresh' })\n .then((result) => result.resources)\n : [],\n capabilities?.resources\n ? client\n .listResourceTemplates(undefined, { cacheMode: 'refresh' })\n .then((result) => result.resourceTemplates)\n : [],\n capabilities?.prompts\n ? client.listPrompts(undefined, { cacheMode: 'refresh' }).then((result) => result.prompts)\n : [],\n ]);\n return { tools, resources, resourceTemplates, prompts };\n }\n\n #isCurrentConnection(connection: Connection): boolean {\n return this.#connection === connection;\n }\n\n #requestRefresh(connection: Connection, context: string): void {\n void this.#queueRefresh(connection, true, context).catch(() => undefined);\n }\n\n #queueRefresh(connection: Connection, notify: boolean, context: string): Promise<void> {\n const refreshRevision = ++connection.refreshRevision;\n let registrationsReplaced = false;\n const refresh = connection.refreshQueue\n .catch(() => undefined)\n .then(async () => {\n const isActive = () =>\n this.#isCurrentConnection(connection) && refreshRevision === connection.refreshRevision;\n if (!isActive()) return;\n\n try {\n const items = await this.#fetchAllFromIframe(connection.client);\n if (!isActive()) return;\n\n this.#unregisterAll(connection);\n registrationsReplaced = true;\n connection.items = items;\n await this.#registerAllOnModelContext(connection, this.itemPrefix, isActive);\n } catch (error) {\n if (!isActive()) {\n if (registrationsReplaced) this.#unregisterAll(connection);\n return;\n }\n this.#failConnection(connection, error, context);\n throw error;\n }\n\n if (!isActive()) {\n this.#unregisterAll(connection);\n return;\n }\n if (notify && connection.ready) this.#dispatchItems('mcp-iframe-items-changed');\n });\n connection.refreshQueue = refresh;\n return refresh;\n }\n\n async #waitForRefreshQueue(connection: Connection): Promise<void> {\n while (this.#isCurrentConnection(connection)) {\n const refresh = connection.refreshQueue;\n await refresh;\n if (refresh === connection.refreshQueue) return;\n }\n }\n\n #dispatchItems(type: 'mcp-iframe-ready' | 'mcp-iframe-items-changed'): void {\n this.dispatchEvent(\n new CustomEvent<MCPIframeItemsEventDetail>(type, {\n detail: {\n tools: this.exposedTools,\n resources: this.exposedResources,\n prompts: this.exposedPrompts,\n },\n })\n );\n }\n\n #dispatchError(error: unknown, context: string): void {\n console.error(`[MCPIframe] ${context}:`, error);\n this.dispatchEvent(\n new CustomEvent<MCPIframeErrorEventDetail>('mcp-iframe-error', { detail: { error } })\n );\n }\n\n #failConnection(connection: Connection, error: unknown, context: string): void {\n if (!this.#invalidateConnection(connection)) return;\n this.#dispatchError(error, context);\n void this.#closeConnection(connection);\n }\n\n #getTargetOrigin(): string {\n const explicit = this.getAttribute('target-origin');\n if (explicit !== null) {\n if (!explicit) throw new Error('target-origin cannot be empty');\n return explicit;\n }\n\n if (\n this.#iframe?.hasAttribute('sandbox') &&\n !this.#iframe.sandbox.contains('allow-same-origin')\n ) {\n throw new Error('Opaque sandboxed iframes require target-origin=\"*\"');\n }\n if (this.hasAttribute('srcdoc')) return window.location.origin;\n\n const src = this.getAttribute('src');\n if (!src) return window.location.origin;\n const url = new URL(src, window.location.href);\n if (url.protocol === 'about:') return window.location.origin;\n if (url.origin === 'null') {\n throw new Error('Opaque iframe sources require target-origin=\"*\"');\n }\n return url.origin;\n }\n\n async #registerAllOnModelContext(\n connection: Connection,\n prefix: string,\n isActive: () => boolean\n ): Promise<void> {\n const modelContext: ModelContext | undefined = document.modelContext ?? navigator.modelContext;\n if (!modelContext) {\n throw new Error('Model Context API not available on parent');\n }\n\n if (this.#nativeToolSyncPending && hasNativeToolSync(modelContext)) {\n // Drain native reconciliation queued by the aborted registrations before reusing names.\n await modelContext.syncNativeTools();\n if (!isActive()) return;\n this.#nativeToolSyncPending = false;\n }\n\n await this.#registerToolsOnModelContext(connection, modelContext, prefix, isActive);\n if (!isActive()) return;\n if (hasMcpBRegistrationExtensions(modelContext)) {\n this.#registerResourcesOnModelContext(connection, modelContext, prefix);\n this.#registerPromptsOnModelContext(connection, modelContext, prefix);\n } else if (\n connection.items.resources.length > 0 ||\n connection.items.resourceTemplates.length > 0 ||\n connection.items.prompts.length > 0\n ) {\n console.warn(\n '[MCPIframe] Parent modelContext does not provide the MCP-B resource and prompt extensions'\n );\n }\n }\n\n async #registerToolsOnModelContext(\n connection: Connection,\n modelContext: ModelContext,\n prefix: string,\n isActive: () => boolean\n ): Promise<void> {\n for (const tool of connection.items.tools) {\n if (!isActive()) return;\n const prefixedName = `${prefix}${tool.name}`;\n if (isDuplicateRegistration(connection.toolRegistrations, prefixedName, 'tool')) continue;\n\n const descriptor: ModelContextTool<Record<string, unknown>, CallToolResult> & {\n inputSchema: InputSchema;\n } = {\n name: prefixedName,\n ...(tool.title !== undefined && { title: tool.title }),\n description: tool.description ?? `Tool from iframe: ${tool.name}`,\n inputSchema: tool.inputSchema,\n ...(tool.annotations?.readOnlyHint !== undefined && {\n annotations: { readOnlyHint: tool.annotations.readOnlyHint },\n }),\n execute: (args) => this.#callIframeTool(tool.name, args),\n };\n const controller = new AbortController();\n connection.toolRegistrations.set(prefixedName, controller);\n try {\n await modelContext.registerTool(descriptor, { signal: controller.signal });\n } catch (error) {\n const wasAborted = controller.signal.aborted;\n if (!wasAborted) {\n this.#nativeToolSyncPending = true;\n controller.abort();\n }\n if (connection.toolRegistrations.get(prefixedName) === controller) {\n connection.toolRegistrations.delete(prefixedName);\n }\n if (!wasAborted) throw error;\n }\n }\n }\n\n #registerResourcesOnModelContext(\n connection: Connection,\n modelContext: McpBRegistrationExtensions,\n prefix: string\n ): void {\n for (const resource of connection.items.resources) {\n const parentUri = createParentResourceUri(prefix, resource.uri);\n if (isDuplicateRegistration(connection.resourceRegistrations, parentUri, 'resource'))\n continue;\n\n const descriptor: ResourceDescriptor = {\n uri: parentUri,\n name: resource.name,\n ...(resource.description !== undefined && { description: resource.description }),\n ...(resource.mimeType !== undefined && { mimeType: resource.mimeType }),\n read: (_uri, _params) => this.#readIframeResource(resource.uri),\n };\n const registration = modelContext.registerResource(descriptor);\n connection.resourceRegistrations.set(parentUri, registration);\n }\n\n for (const resourceTemplate of connection.items.resourceTemplates) {\n const childTemplate = new UriTemplate(resourceTemplate.uriTemplate);\n const parentUri = createParentResourceUri(\n prefix,\n resourceTemplate.uriTemplate,\n childTemplate.variableNames\n );\n if (isDuplicateRegistration(connection.resourceRegistrations, parentUri, 'resource'))\n continue;\n\n const descriptor: ResourceDescriptor = {\n uri: parentUri,\n name: resourceTemplate.name,\n ...(resourceTemplate.description !== undefined && {\n description: resourceTemplate.description,\n }),\n ...(resourceTemplate.mimeType !== undefined && { mimeType: resourceTemplate.mimeType }),\n read: (_uri, params) =>\n this.#readIframeResource(childTemplate.expand(decodeTemplateVariables(params ?? {}))),\n };\n const registration = modelContext.registerResource(descriptor);\n connection.resourceRegistrations.set(parentUri, registration);\n }\n }\n\n #registerPromptsOnModelContext(\n connection: Connection,\n modelContext: McpBRegistrationExtensions,\n prefix: string\n ): void {\n for (const prompt of connection.items.prompts) {\n const prefixedName = `${prefix}${prompt.name}`;\n if (isDuplicateRegistration(connection.promptRegistrations, prefixedName, 'prompt')) continue;\n\n const descriptor: PromptDescriptor = {\n name: prefixedName,\n ...(prompt.description !== undefined && { description: prompt.description }),\n ...(prompt.arguments &&\n prompt.arguments.length > 0 && {\n argsSchema: {\n type: 'object',\n properties: Object.fromEntries(\n prompt.arguments.map((arg) => [\n arg.name,\n {\n type: 'string',\n ...(arg.description !== undefined && { description: arg.description }),\n },\n ])\n ),\n required: prompt.arguments.filter((a) => a.required).map((a) => a.name),\n } satisfies InputSchema,\n }),\n get: (args) => this.#getIframePrompt(prompt.name, args),\n };\n const registration = modelContext.registerPrompt(descriptor);\n connection.promptRegistrations.set(prefixedName, registration);\n }\n }\n\n #unregisterAll(connection: Connection): void {\n const tools = [...connection.toolRegistrations.values()];\n const registrations = [\n ...connection.resourceRegistrations.values(),\n ...connection.promptRegistrations.values(),\n ];\n connection.toolRegistrations.clear();\n connection.resourceRegistrations.clear();\n connection.promptRegistrations.clear();\n connection.items = emptyItems();\n if (tools.length > 0) this.#nativeToolSyncPending = true;\n\n for (const controller of tools) {\n try {\n controller.abort();\n } catch (error) {\n console.warn('[MCPIframe] Failed to unregister a parent tool:', error);\n }\n }\n for (const registration of registrations) {\n try {\n registration.unregister();\n } catch (error) {\n console.warn('[MCPIframe] Failed to unregister a parent item:', error);\n }\n }\n }\n\n #requireClient(): Client {\n const connection = this.#connection;\n if (!connection?.ready) {\n throw new Error('Not connected to iframe MCP server');\n }\n return connection.client;\n }\n\n #getCallTimeout(): number {\n const timeout = Number(this.getAttribute('call-timeout'));\n return Number.isSafeInteger(timeout) && timeout > 0 ? timeout : DEFAULT_CALL_TIMEOUT;\n }\n\n async #callIframeTool(toolName: string, args: Record<string, unknown>): Promise<CallToolResult> {\n return this.#requireClient().callTool(\n { name: toolName, arguments: args },\n { timeout: this.#getCallTimeout() }\n );\n }\n\n async #readIframeResource(uri: string): Promise<ReadResourceResult> {\n return this.#requireClient().readResource({ uri }, { timeout: this.#getCallTimeout() });\n }\n\n async #getIframePrompt(name: string, args: Record<string, string>): Promise<GetPromptResult> {\n return this.#requireClient().getPrompt(\n { name, arguments: args },\n { timeout: this.#getCallTimeout() }\n );\n }\n\n async #reconnect(): Promise<void> {\n const requestGeneration = ++this.#connectionRequestGeneration;\n await this.#disconnect();\n if (requestGeneration !== this.#connectionRequestGeneration || !this.isConnected) return;\n await this.#connect(requestGeneration);\n }\n\n async #disconnect(connection = this.#connection): Promise<void> {\n if (!connection || !this.#invalidateConnection(connection)) return;\n await this.#closeConnection(connection);\n }\n\n #invalidateConnection(connection: Connection): boolean {\n if (!this.#isCurrentConnection(connection)) return false;\n this.#connection = null;\n ++connection.refreshRevision;\n connection.ready = false;\n delete connection.client.onclose;\n delete connection.client.onerror;\n this.#unregisterAll(connection);\n return true;\n }\n\n async #closeConnection(connection: Connection): Promise<void> {\n try {\n await connection.client.close();\n } catch (error) {\n console.warn('[MCPIframeElement] Error closing client during disconnect:', error);\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mcp-iframe': MCPIframeElement;\n }\n}\n\n/** Register the custom element with a custom tag name */\nexport function registerMCPIframeElement(tagName = 'mcp-iframe'): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {\n customElements.define(tagName, MCPIframeElement);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MCPIframeElement-CYns0bdY.js","names":["#iframe","#reconnect","#createIframe","#connectionRequestGeneration","#disconnect","#connection","#requestRefresh","#queueRefresh","#waitForRefreshQueue","#isCurrentConnection","#connect","#connectionAttempt","#connectCurrent","#getTargetOrigin","#failConnection","#dispatchItems","#dispatchError","#fetchAllFromIframe","#unregisterAll","#registerAllOnModelContext","#invalidateConnection","#closeConnection","#nativeToolSyncPending","#registerToolsOnModelContext","#registerResourcesOnModelContext","#registerPromptsOnModelContext","#callIframeTool","#readIframeResource","#getIframePrompt","#requireClient","#getCallTimeout"],"sources":["../src/MCPIframeElement.ts"],"sourcesContent":["/**\n * MCPIframe Custom Element\n *\n * A custom element that wraps an iframe and automatically exposes tools,\n * resources, and prompts registered in the iframe's MCP server to the\n * parent page's Model Context API.\n *\n * The iframe should expose its MCP server through `document.modelContext`.\n * Older runtimes that only expose `navigator.modelContext` remain supported.\n *\n * @example\n * ```html\n * <mcp-iframe src=\"./child-app.html\" id=\"my-app\"></mcp-iframe>\n * ```\n *\n * Tool and prompt names use the element's ID as a prefix. Resources use a wrapper URI:\n * - Child registers tool \"calculate\" -> Parent sees \"my-app_calculate\"\n * - Child registers resource \"config://settings\" -> Parent sees an \"mcp-iframe:\" wrapper URI\n * - Child registers prompt \"help\" -> Parent sees \"my-app_help\"\n *\n * Note: The prefix separator defaults to underscore (_) to ensure WebMCP compatibility.\n * The parent model context validates the final prefixed tool name.\n *\n * @example\n * ```typescript\n * const mcpIframe = document.querySelector('mcp-iframe');\n * mcpIframe.addEventListener('mcp-iframe-ready', (e) => {\n * console.log('Tools:', e.detail.tools);\n * console.log('Resources:', e.detail.resources);\n * console.log('Prompts:', e.detail.prompts);\n * });\n * ```\n */\n\nimport { DEFAULT_IFRAME_CHANNEL_ID, IframeParentTransport } from '@mcp-b/transports';\nimport {\n type BrowserMcpServer,\n type PromptDescriptor,\n type ResourceDescriptor,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type {\n CallToolResult,\n InputSchema,\n ModelContext,\n ModelContextTool,\n RegistrationHandle,\n} from '@mcp-b/webmcp-types';\nimport {\n Client,\n UriTemplate,\n type GetPromptResult,\n type Prompt,\n type ReadResourceResult,\n type Resource,\n type ResourceTemplateType,\n type Tool,\n type Variables,\n} from '@modelcontextprotocol/client';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nconst DEFAULT_CALL_TIMEOUT = 30000;\nconst DEFAULT_PREFIX_SEPARATOR = '_';\n\ntype McpBRegistrationExtensions = Pick<BrowserMcpServer, 'registerPrompt' | 'registerResource'>;\ntype NativeToolSyncExtension = Pick<BrowserMcpServer, 'syncNativeTools'>;\n\ninterface McpItems {\n tools: Tool[];\n resources: Resource[];\n resourceTemplates: ResourceTemplateType[];\n prompts: Prompt[];\n}\n\ninterface Connection {\n client: Client;\n ready: boolean;\n refreshRevision: number;\n refreshQueue: Promise<void>;\n items: McpItems;\n toolRegistrations: Map<string, AbortController>;\n resourceRegistrations: Map<string, RegistrationHandle>;\n promptRegistrations: Map<string, RegistrationHandle>;\n}\n\nconst emptyItems = (): McpItems => ({\n tools: [],\n resources: [],\n resourceTemplates: [],\n prompts: [],\n});\n\nfunction hasMcpBRegistrationExtensions(\n modelContext: ModelContext\n): modelContext is ModelContext & McpBRegistrationExtensions {\n return (\n 'registerResource' in modelContext &&\n typeof modelContext.registerResource === 'function' &&\n 'registerPrompt' in modelContext &&\n typeof modelContext.registerPrompt === 'function'\n );\n}\n\nfunction hasNativeToolSync(\n modelContext: ModelContext\n): modelContext is ModelContext & NativeToolSyncExtension {\n return 'syncNativeTools' in modelContext && typeof modelContext.syncNativeTools === 'function';\n}\n\n/**\n * Sanitizes a string to contain only valid MCP name characters.\n * Replaces invalid characters with underscores.\n */\nfunction sanitizeMCPNamePart(str: string): string {\n return str.replace(/[^a-zA-Z0-9_.-]/g, '_');\n}\n\nfunction createParentResourceUri(\n source: string,\n childUri: string,\n variables: readonly string[] = []\n): string {\n const parentUri = new URL('mcp-iframe:');\n parentUri.searchParams.set('source', source);\n parentUri.searchParams.set('uri', childUri);\n return [...new Set(variables)].reduce(\n (uri, variable, index) => `${uri}&variable-${index}={${variable}*}`,\n parentUri.href\n );\n}\n\n/**\n * Registration maps are keyed by the parent-visible name or URI, so a second item with the same\n * key can only shadow a live registration that `#unregisterAll` would then never tear down.\n */\nfunction isDuplicateRegistration(\n registrations: ReadonlyMap<string, unknown>,\n key: string,\n kind: string\n): boolean {\n if (!registrations.has(key)) return false;\n console.warn(`[MCPIframe] Ignoring duplicate iframe ${kind} \"${key}\"`);\n return true;\n}\n\nfunction decodeTemplateVariables(variables: Variables): Variables {\n return Object.fromEntries(\n Object.entries(variables).map(([name, value]) => [\n name,\n Array.isArray(value) ? value.map(decodeURIComponent) : decodeURIComponent(value),\n ])\n );\n}\n\n/** Standard iframe attributes that are mirrored to the internal iframe */\nconst IFRAME_ATTRIBUTES = [\n 'src',\n 'srcdoc',\n 'name',\n 'sandbox',\n 'allow',\n 'allowfullscreen',\n 'width',\n 'height',\n 'loading',\n 'referrerpolicy',\n 'credentialless',\n] satisfies readonly string[];\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Names of items currently exposed on the parent model context. */\nexport interface MCPIframeItemsEventDetail {\n tools: string[];\n resources: string[];\n prompts: string[];\n}\n\n/** Custom event detail for mcp-iframe-error */\nexport interface MCPIframeErrorEventDetail {\n error: unknown;\n}\n\nexport interface MCPIframeEventMap {\n 'mcp-iframe-ready': CustomEvent<MCPIframeItemsEventDetail>;\n 'mcp-iframe-error': CustomEvent<MCPIframeErrorEventDetail>;\n 'mcp-iframe-items-changed': CustomEvent<MCPIframeItemsEventDetail>;\n}\n\n// ============================================================================\n// MCPIframeElement\n// ============================================================================\n\n/**\n * MCPIframe Custom Element\n *\n * Wraps an iframe and exposes its MCP tools, resources, and prompts\n * to the parent's Model Context API.\n *\n * @fires mcp-iframe-ready - When connected to iframe's MCP server\n * @fires mcp-iframe-error - When the connection or an item refresh fails\n * @fires mcp-iframe-items-changed - When items are refreshed\n */\nexport class MCPIframeElement extends HTMLElement {\n declare addEventListener: (<K extends keyof MCPIframeEventMap>(\n type: K,\n listener: (this: MCPIframeElement, event: MCPIframeEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions\n ) => void) &\n HTMLElement['addEventListener'];\n\n declare removeEventListener: (<K extends keyof MCPIframeEventMap>(\n type: K,\n listener: (this: MCPIframeElement, event: MCPIframeEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions\n ) => void) &\n HTMLElement['removeEventListener'];\n\n #iframe: HTMLIFrameElement | null = null;\n #connection: Connection | null = null;\n #connectionAttempt: Promise<void> | null = null;\n #connectionRequestGeneration = 0;\n #nativeToolSyncPending = false;\n\n static get observedAttributes(): string[] {\n return [\n ...IFRAME_ATTRIBUTES,\n 'id',\n 'target-origin',\n 'channel',\n 'call-timeout',\n 'prefix-separator',\n ];\n }\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n\n // ==================== Lifecycle ====================\n\n connectedCallback(): void {\n if (this.#iframe) {\n void this.#reconnect();\n } else {\n this.#createIframe();\n }\n }\n\n disconnectedCallback(): void {\n ++this.#connectionRequestGeneration;\n void this.#disconnect();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'target-origin' || name === 'channel') {\n if (this.#iframe && this.isConnected) void this.#reconnect();\n return;\n }\n\n if (name === 'call-timeout') {\n const timeout = Number(newValue);\n if (newValue !== null && (!Number.isSafeInteger(timeout) || timeout <= 0)) {\n console.warn(\n `[MCPIframe] Invalid call-timeout \"${newValue}\". Using ${DEFAULT_CALL_TIMEOUT}.`\n );\n }\n return;\n }\n\n if (name === 'id' || name === 'prefix-separator') {\n if (name === 'prefix-separator' && newValue !== null) {\n const sanitized = sanitizeMCPNamePart(newValue);\n if (sanitized !== newValue) {\n console.warn(`[MCPIframe] Invalid prefix-separator \"${newValue}\". Using \"${sanitized}\".`);\n }\n }\n const connection = this.#connection;\n if (connection) {\n this.#requestRefresh(connection, 'Failed to update parent registrations');\n }\n return;\n }\n\n if (!this.#iframe || !IFRAME_ATTRIBUTES.includes(name)) return;\n if (newValue === null) {\n this.#iframe.removeAttribute(name);\n } else {\n this.#iframe.setAttribute(name, newValue);\n }\n if (name === 'src' || name === 'srcdoc') {\n ++this.#connectionRequestGeneration;\n void this.#disconnect();\n } else if (name === 'name') {\n const connection = this.#connection;\n if (connection) {\n this.#requestRefresh(connection, 'Failed to update parent registrations');\n }\n }\n }\n\n // ==================== Public API ====================\n\n /** The wrapped iframe element */\n get iframe(): HTMLIFrameElement | null {\n return this.#iframe;\n }\n\n /** Whether the element is connected to the iframe's MCP server */\n get ready(): boolean {\n return this.#connection?.ready ?? false;\n }\n\n /** List of exposed tool names (with prefix) */\n get exposedTools(): string[] {\n return Array.from(this.#connection?.toolRegistrations.keys() ?? []);\n }\n\n /** List of exposed parent-side resource wrapper URIs */\n get exposedResources(): string[] {\n return Array.from(this.#connection?.resourceRegistrations.keys() ?? []);\n }\n\n /** List of exposed prompt names (with prefix) */\n get exposedPrompts(): string[] {\n return Array.from(this.#connection?.promptRegistrations.keys() ?? []);\n }\n\n /** The item name prefix (id + separator), sanitized for MCP compatibility */\n get itemPrefix(): string {\n const rawId = this.id || this.getAttribute('name') || 'iframe';\n const id = sanitizeMCPNamePart(rawId);\n const separator = sanitizeMCPNamePart(\n this.getAttribute('prefix-separator') ?? DEFAULT_PREFIX_SEPARATOR\n );\n return `${id}${separator}`;\n }\n\n /** Manually refresh all items from the iframe */\n async refresh(): Promise<void> {\n const connection = this.#connection;\n if (!connection?.ready) {\n throw new Error('Not connected to iframe MCP server');\n }\n\n await this.#queueRefresh(connection, true, 'Failed to refresh iframe items');\n await this.#waitForRefreshQueue(connection);\n if (!this.#isCurrentConnection(connection) || !connection.ready) {\n throw new Error('Iframe connection changed before refresh completed');\n }\n }\n\n // ==================== Private Methods ====================\n\n #createIframe(): void {\n if (this.#iframe) return;\n\n this.#iframe = document.createElement('iframe');\n\n // Mirror all iframe attributes\n for (const attr of IFRAME_ATTRIBUTES) {\n const value = this.getAttribute(attr);\n if (value !== null) {\n this.#iframe.setAttribute(attr, value);\n }\n }\n\n this.#iframe.style.border = 'none';\n\n // src/srcdoc changes only tear down; the load event rebuilds the connection.\n this.#iframe.addEventListener('load', () => void this.#reconnect());\n\n this.shadowRoot?.appendChild(this.#iframe);\n }\n\n async #connect(requestGeneration: number): Promise<void> {\n const activeAttempt = this.#connectionAttempt;\n if (activeAttempt) {\n await activeAttempt.catch(() => undefined);\n }\n const iframe = this.#iframe;\n if (requestGeneration !== this.#connectionRequestGeneration || !iframe || !this.isConnected) {\n return;\n }\n\n const attempt = this.#connectCurrent(requestGeneration, iframe);\n this.#connectionAttempt = attempt;\n try {\n await attempt;\n } finally {\n if (this.#connectionAttempt === attempt) {\n this.#connectionAttempt = null;\n }\n }\n }\n\n async #connectCurrent(requestGeneration: number, iframe: HTMLIFrameElement): Promise<void> {\n let connection: Connection | undefined;\n\n try {\n const transport = new IframeParentTransport({\n iframe,\n targetOrigin: this.#getTargetOrigin(),\n channelId: this.getAttribute('channel') ?? DEFAULT_IFRAME_CHANNEL_ID,\n });\n const onListChanged = () => {\n if (connection) this.#requestRefresh(connection, 'Failed to refresh iframe items');\n };\n const listChanged = { autoRefresh: false, debounceMs: 0, onChanged: onListChanged };\n const client = new Client(\n { name: `MCPIframe:${this.id || 'anonymous'}`, version: '1.0.0' },\n {\n versionNegotiation: { mode: 'auto' },\n listChanged: { tools: listChanged, resources: listChanged, prompts: listChanged },\n }\n );\n const currentConnection: Connection = {\n client,\n ready: false,\n refreshRevision: 0,\n refreshQueue: Promise.resolve(),\n items: emptyItems(),\n toolRegistrations: new Map(),\n resourceRegistrations: new Map(),\n promptRegistrations: new Map(),\n };\n connection = currentConnection;\n this.#connection = currentConnection;\n client.onclose = () => {\n if (currentConnection.ready) void this.#disconnect(currentConnection);\n };\n client.onerror = (error) => {\n this.#failConnection(currentConnection, error, 'Iframe MCP client error');\n };\n\n await client.connect(transport);\n if (\n requestGeneration !== this.#connectionRequestGeneration ||\n !this.#isCurrentConnection(currentConnection)\n ) {\n return;\n }\n\n await this.#queueRefresh(currentConnection, false, 'Failed to connect');\n await this.#waitForRefreshQueue(currentConnection);\n if (!this.#isCurrentConnection(currentConnection)) return;\n currentConnection.ready = true;\n this.#dispatchItems('mcp-iframe-ready');\n } catch (error) {\n if (\n requestGeneration !== this.#connectionRequestGeneration ||\n !this.isConnected ||\n (connection && !this.#isCurrentConnection(connection))\n ) {\n return;\n }\n if (connection) {\n this.#failConnection(connection, error, 'Failed to connect');\n } else {\n this.#dispatchError(error, 'Failed to connect');\n }\n }\n }\n\n async #fetchAllFromIframe(client: Client): Promise<McpItems> {\n const capabilities = client.getServerCapabilities();\n const [tools, resources, resourceTemplates, prompts] = await Promise.all([\n capabilities?.tools\n ? client.listTools(undefined, { cacheMode: 'refresh' }).then((result) => result.tools)\n : [],\n capabilities?.resources\n ? client\n .listResources(undefined, { cacheMode: 'refresh' })\n .then((result) => result.resources)\n : [],\n capabilities?.resources\n ? client\n .listResourceTemplates(undefined, { cacheMode: 'refresh' })\n .then((result) => result.resourceTemplates)\n : [],\n capabilities?.prompts\n ? client.listPrompts(undefined, { cacheMode: 'refresh' }).then((result) => result.prompts)\n : [],\n ]);\n return { tools, resources, resourceTemplates, prompts };\n }\n\n #isCurrentConnection(connection: Connection): boolean {\n return this.#connection === connection;\n }\n\n #requestRefresh(connection: Connection, context: string): void {\n void this.#queueRefresh(connection, true, context).catch(() => undefined);\n }\n\n #queueRefresh(connection: Connection, notify: boolean, context: string): Promise<void> {\n const refreshRevision = ++connection.refreshRevision;\n let registrationsReplaced = false;\n const refresh = connection.refreshQueue\n .catch(() => undefined)\n .then(async () => {\n const isActive = () =>\n this.#isCurrentConnection(connection) && refreshRevision === connection.refreshRevision;\n if (!isActive()) return;\n\n try {\n const items = await this.#fetchAllFromIframe(connection.client);\n if (!isActive()) return;\n\n this.#unregisterAll(connection);\n registrationsReplaced = true;\n connection.items = items;\n await this.#registerAllOnModelContext(connection, this.itemPrefix, isActive);\n } catch (error) {\n if (!isActive()) {\n if (registrationsReplaced) this.#unregisterAll(connection);\n return;\n }\n this.#failConnection(connection, error, context);\n throw error;\n }\n\n if (!isActive()) {\n this.#unregisterAll(connection);\n return;\n }\n if (notify && connection.ready) this.#dispatchItems('mcp-iframe-items-changed');\n });\n connection.refreshQueue = refresh;\n return refresh;\n }\n\n async #waitForRefreshQueue(connection: Connection): Promise<void> {\n while (this.#isCurrentConnection(connection)) {\n const refresh = connection.refreshQueue;\n await refresh;\n if (refresh === connection.refreshQueue) return;\n }\n }\n\n #dispatchItems(type: 'mcp-iframe-ready' | 'mcp-iframe-items-changed'): void {\n this.dispatchEvent(\n new CustomEvent<MCPIframeItemsEventDetail>(type, {\n detail: {\n tools: this.exposedTools,\n resources: this.exposedResources,\n prompts: this.exposedPrompts,\n },\n })\n );\n }\n\n #dispatchError(error: unknown, context: string): void {\n console.error(`[MCPIframe] ${context}:`, error);\n this.dispatchEvent(\n new CustomEvent<MCPIframeErrorEventDetail>('mcp-iframe-error', { detail: { error } })\n );\n }\n\n #failConnection(connection: Connection, error: unknown, context: string): void {\n if (!this.#invalidateConnection(connection)) return;\n this.#dispatchError(error, context);\n void this.#closeConnection(connection);\n }\n\n #getTargetOrigin(): string {\n const explicit = this.getAttribute('target-origin');\n if (explicit !== null) {\n if (!explicit) throw new Error('target-origin cannot be empty');\n return explicit;\n }\n\n if (\n this.#iframe?.hasAttribute('sandbox') &&\n !this.#iframe.sandbox.contains('allow-same-origin')\n ) {\n throw new Error('Opaque sandboxed iframes require target-origin=\"*\"');\n }\n if (this.hasAttribute('srcdoc')) return window.location.origin;\n\n const src = this.getAttribute('src');\n if (!src) return window.location.origin;\n const url = new URL(src, window.location.href);\n if (url.protocol === 'about:') return window.location.origin;\n if (url.origin === 'null') {\n throw new Error('Opaque iframe sources require target-origin=\"*\"');\n }\n return url.origin;\n }\n\n async #registerAllOnModelContext(\n connection: Connection,\n prefix: string,\n isActive: () => boolean\n ): Promise<void> {\n const modelContext: ModelContext | undefined = document.modelContext ?? navigator.modelContext;\n if (!modelContext) {\n throw new Error('Model Context API not available on parent');\n }\n\n if (this.#nativeToolSyncPending && hasNativeToolSync(modelContext)) {\n // Drain native reconciliation queued by the aborted registrations before reusing names.\n await modelContext.syncNativeTools();\n if (!isActive()) return;\n this.#nativeToolSyncPending = false;\n }\n\n await this.#registerToolsOnModelContext(connection, modelContext, prefix, isActive);\n if (!isActive()) return;\n if (hasMcpBRegistrationExtensions(modelContext)) {\n this.#registerResourcesOnModelContext(connection, modelContext, prefix);\n this.#registerPromptsOnModelContext(connection, modelContext, prefix);\n } else if (\n connection.items.resources.length > 0 ||\n connection.items.resourceTemplates.length > 0 ||\n connection.items.prompts.length > 0\n ) {\n console.warn(\n '[MCPIframe] Parent modelContext does not provide the MCP-B resource and prompt extensions'\n );\n }\n }\n\n async #registerToolsOnModelContext(\n connection: Connection,\n modelContext: ModelContext,\n prefix: string,\n isActive: () => boolean\n ): Promise<void> {\n for (const tool of connection.items.tools) {\n if (!isActive()) return;\n const prefixedName = `${prefix}${tool.name}`;\n if (isDuplicateRegistration(connection.toolRegistrations, prefixedName, 'tool')) continue;\n\n const descriptor: ModelContextTool<Record<string, unknown>, CallToolResult> & {\n inputSchema: InputSchema;\n } = {\n name: prefixedName,\n ...(tool.title !== undefined && { title: tool.title }),\n description: tool.description ?? `Tool from iframe: ${tool.name}`,\n inputSchema: tool.inputSchema,\n ...(tool.annotations?.readOnlyHint !== undefined && {\n annotations: { readOnlyHint: tool.annotations.readOnlyHint },\n }),\n execute: (args) => this.#callIframeTool(tool.name, args),\n };\n const controller = new AbortController();\n connection.toolRegistrations.set(prefixedName, controller);\n try {\n await modelContext.registerTool(descriptor, { signal: controller.signal });\n } catch (error) {\n const wasAborted = controller.signal.aborted;\n if (!wasAborted) {\n this.#nativeToolSyncPending = true;\n controller.abort();\n }\n if (connection.toolRegistrations.get(prefixedName) === controller) {\n connection.toolRegistrations.delete(prefixedName);\n }\n if (!wasAborted) throw error;\n }\n }\n }\n\n #registerResourcesOnModelContext(\n connection: Connection,\n modelContext: McpBRegistrationExtensions,\n prefix: string\n ): void {\n for (const resource of connection.items.resources) {\n const parentUri = createParentResourceUri(prefix, resource.uri);\n if (isDuplicateRegistration(connection.resourceRegistrations, parentUri, 'resource'))\n continue;\n\n const descriptor: ResourceDescriptor = {\n uri: parentUri,\n name: resource.name,\n ...(resource.description !== undefined && { description: resource.description }),\n ...(resource.mimeType !== undefined && { mimeType: resource.mimeType }),\n read: (_uri, _params) => this.#readIframeResource(resource.uri),\n };\n const registration = modelContext.registerResource(descriptor);\n connection.resourceRegistrations.set(parentUri, registration);\n }\n\n for (const resourceTemplate of connection.items.resourceTemplates) {\n const childTemplate = new UriTemplate(resourceTemplate.uriTemplate);\n const parentUri = createParentResourceUri(\n prefix,\n resourceTemplate.uriTemplate,\n childTemplate.variableNames\n );\n if (isDuplicateRegistration(connection.resourceRegistrations, parentUri, 'resource'))\n continue;\n\n const descriptor: ResourceDescriptor = {\n uri: parentUri,\n name: resourceTemplate.name,\n ...(resourceTemplate.description !== undefined && {\n description: resourceTemplate.description,\n }),\n ...(resourceTemplate.mimeType !== undefined && { mimeType: resourceTemplate.mimeType }),\n read: (_uri, params) =>\n this.#readIframeResource(childTemplate.expand(decodeTemplateVariables(params ?? {}))),\n };\n const registration = modelContext.registerResource(descriptor);\n connection.resourceRegistrations.set(parentUri, registration);\n }\n }\n\n #registerPromptsOnModelContext(\n connection: Connection,\n modelContext: McpBRegistrationExtensions,\n prefix: string\n ): void {\n for (const prompt of connection.items.prompts) {\n const prefixedName = `${prefix}${prompt.name}`;\n if (isDuplicateRegistration(connection.promptRegistrations, prefixedName, 'prompt')) continue;\n\n const descriptor: PromptDescriptor = {\n name: prefixedName,\n ...(prompt.description !== undefined && { description: prompt.description }),\n ...(prompt.arguments &&\n prompt.arguments.length > 0 && {\n argsSchema: {\n type: 'object',\n properties: Object.fromEntries(\n prompt.arguments.map((arg) => [\n arg.name,\n {\n type: 'string',\n ...(arg.description !== undefined && { description: arg.description }),\n },\n ])\n ),\n required: prompt.arguments.filter((a) => a.required).map((a) => a.name),\n } satisfies InputSchema,\n }),\n get: (args) => this.#getIframePrompt(prompt.name, args),\n };\n const registration = modelContext.registerPrompt(descriptor);\n connection.promptRegistrations.set(prefixedName, registration);\n }\n }\n\n #unregisterAll(connection: Connection): void {\n const tools = [...connection.toolRegistrations.values()];\n const registrations = [\n ...connection.resourceRegistrations.values(),\n ...connection.promptRegistrations.values(),\n ];\n connection.toolRegistrations.clear();\n connection.resourceRegistrations.clear();\n connection.promptRegistrations.clear();\n connection.items = emptyItems();\n if (tools.length > 0) this.#nativeToolSyncPending = true;\n\n for (const controller of tools) {\n try {\n controller.abort();\n } catch (error) {\n console.warn('[MCPIframe] Failed to unregister a parent tool:', error);\n }\n }\n for (const registration of registrations) {\n try {\n registration.unregister();\n } catch (error) {\n console.warn('[MCPIframe] Failed to unregister a parent item:', error);\n }\n }\n }\n\n #requireClient(): Client {\n const connection = this.#connection;\n if (!connection?.ready) {\n throw new Error('Not connected to iframe MCP server');\n }\n return connection.client;\n }\n\n #getCallTimeout(): number {\n const timeout = Number(this.getAttribute('call-timeout'));\n return Number.isSafeInteger(timeout) && timeout > 0 ? timeout : DEFAULT_CALL_TIMEOUT;\n }\n\n async #callIframeTool(toolName: string, args: Record<string, unknown>): Promise<CallToolResult> {\n return this.#requireClient().callTool(\n { name: toolName, arguments: args },\n { timeout: this.#getCallTimeout() }\n );\n }\n\n async #readIframeResource(uri: string): Promise<ReadResourceResult> {\n return this.#requireClient().readResource({ uri }, { timeout: this.#getCallTimeout() });\n }\n\n async #getIframePrompt(name: string, args: Record<string, string>): Promise<GetPromptResult> {\n return this.#requireClient().getPrompt(\n { name, arguments: args },\n { timeout: this.#getCallTimeout() }\n );\n }\n\n async #reconnect(): Promise<void> {\n const requestGeneration = ++this.#connectionRequestGeneration;\n await this.#disconnect();\n if (requestGeneration !== this.#connectionRequestGeneration || !this.isConnected) return;\n await this.#connect(requestGeneration);\n }\n\n async #disconnect(connection = this.#connection): Promise<void> {\n if (!connection || !this.#invalidateConnection(connection)) return;\n await this.#closeConnection(connection);\n }\n\n #invalidateConnection(connection: Connection): boolean {\n if (!this.#isCurrentConnection(connection)) return false;\n this.#connection = null;\n ++connection.refreshRevision;\n connection.ready = false;\n delete connection.client.onclose;\n delete connection.client.onerror;\n this.#unregisterAll(connection);\n return true;\n }\n\n async #closeConnection(connection: Connection): Promise<void> {\n try {\n await connection.client.close();\n } catch (error) {\n console.warn('[MCPIframeElement] Error closing client during disconnect:', error);\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mcp-iframe': MCPIframeElement;\n }\n}\n\n/** Register the custom element with a custom tag name */\nexport function registerMCPIframeElement(tagName = 'mcp-iframe'): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {\n customElements.define(tagName, MCPIframeElement);\n }\n}\n"],"mappings":"gKA+DA,MAAM,EAAuB,IAwBvB,OAA8B,CAClC,MAAO,CAAC,EACR,UAAW,CAAC,EACZ,kBAAmB,CAAC,EACpB,QAAS,CAAC,CACZ,GAEA,SAAS,EACP,EAC2D,CAC3D,MACE,qBAAsB,GACtB,OAAO,EAAa,kBAAqB,YACzC,mBAAoB,GACpB,OAAO,EAAa,gBAAmB,UAE3C,CAEA,SAAS,EACP,EACwD,CACxD,MAAO,oBAAqB,GAAgB,OAAO,EAAa,iBAAoB,UACtF,CAMA,SAAS,EAAoB,EAAqB,CAChD,OAAO,EAAI,QAAQ,mBAAoB,GAAG,CAC5C,CAEA,SAAS,EACP,EACA,EACA,EAA+B,CAAC,EACxB,CACR,IAAM,EAAY,IAAI,IAAI,aAAa,EAGvC,OAFA,EAAU,aAAa,IAAI,SAAU,CAAM,EAC3C,EAAU,aAAa,IAAI,MAAO,CAAQ,EACnC,CAAC,GAAG,IAAI,IAAI,CAAS,CAAC,EAAE,QAC5B,EAAK,EAAU,IAAU,GAAG,EAAI,YAAY,EAAM,IAAI,EAAS,IAChE,EAAU,IACZ,CACF,CAMA,SAAS,EACP,EACA,EACA,EACS,CAGT,OAFK,EAAc,IAAI,CAAG,GAC1B,QAAQ,KAAK,yCAAyC,EAAK,IAAI,EAAI,EAAE,EAC9D,IAF6B,EAGtC,CAEA,SAAS,EAAwB,EAAiC,CAChE,OAAO,OAAO,YACZ,OAAO,QAAQ,CAAS,EAAE,KAAK,CAAC,EAAM,KAAW,CAC/C,EACA,MAAM,QAAQ,CAAK,EAAI,EAAM,IAAI,kBAAkB,EAAI,mBAAmB,CAAK,CACjF,CAAC,CACH,CACF,CAGA,MAAM,EAAoB,CACxB,MACA,SACA,OACA,UACA,QACA,kBACA,QACA,SACA,UACA,iBACA,gBACF,EAsCA,IAAa,EAAb,cAAsC,WAAY,CAehD,GAAoC,KACpC,GAAiC,KACjC,GAA2C,KAC3C,GAA+B,EAC/B,GAAyB,GAEzB,WAAW,oBAA+B,CACxC,MAAO,CACL,GAAG,EACH,KACA,gBACA,UACA,eACA,kBACF,CACF,CAEA,aAAc,CACZ,MAAM,EACN,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,CACpC,CAIA,mBAA0B,CACpB,KAAKA,GACP,KAAUC,GAAW,EAErB,KAAKC,GAAc,CAEvB,CAEA,sBAA6B,CAC3B,EAAE,KAAKC,GACP,KAAUC,GAAY,CACxB,CAEA,yBAAyB,EAAc,EAAyB,EAA+B,CACzF,OAAa,EAEjB,IAAI,IAAS,iBAAmB,IAAS,UAAW,CAC9C,KAAKJ,IAAW,KAAK,aAAa,KAAUC,GAAW,EAC3D,MACF,CAEA,GAAI,IAAS,eAAgB,CAC3B,IAAM,EAAU,OAAO,CAAQ,EAC3B,IAAa,OAAS,CAAC,OAAO,cAAc,CAAO,GAAK,GAAW,IACrE,QAAQ,KACN,qCAAqC,EAAS,WAAW,EAAqB,EAChF,EAEF,MACF,CAEA,GAAI,IAAS,MAAQ,IAAS,mBAAoB,CAChD,GAAI,IAAS,oBAAsB,IAAa,KAAM,CACpD,IAAM,EAAY,EAAoB,CAAQ,EAC1C,IAAc,GAChB,QAAQ,KAAK,yCAAyC,EAAS,YAAY,EAAU,GAAG,CAE5F,CACA,IAAM,EAAa,KAAKI,GACpB,GACF,KAAKC,GAAgB,EAAY,uCAAuC,EAE1E,MACF,CAEI,MAAC,KAAKN,IAAW,CAAC,EAAkB,SAAS,CAAI,GAMrD,IALI,IAAa,KACf,KAAKA,GAAQ,gBAAgB,CAAI,EAEjC,KAAKA,GAAQ,aAAa,EAAM,CAAQ,EAEtC,IAAS,OAAS,IAAS,SAC7B,EAAE,KAAKG,GACP,KAAUC,GAAY,OACjB,GAAI,IAAS,OAAQ,CAC1B,IAAM,EAAa,KAAKC,GACpB,GACF,KAAKC,GAAgB,EAAY,uCAAuC,CAE5E,EAxCA,CAyCF,CAKA,IAAI,QAAmC,CACrC,OAAO,KAAKN,EACd,CAGA,IAAI,OAAiB,CACnB,OAAO,KAAKK,IAAa,OAAS,EACpC,CAGA,IAAI,cAAyB,CAC3B,OAAO,MAAM,KAAK,KAAKA,IAAa,kBAAkB,KAAK,GAAK,CAAC,CAAC,CACpE,CAGA,IAAI,kBAA6B,CAC/B,OAAO,MAAM,KAAK,KAAKA,IAAa,sBAAsB,KAAK,GAAK,CAAC,CAAC,CACxE,CAGA,IAAI,gBAA2B,CAC7B,OAAO,MAAM,KAAK,KAAKA,IAAa,oBAAoB,KAAK,GAAK,CAAC,CAAC,CACtE,CAGA,IAAI,YAAqB,CAMvB,MAAO,GAJI,EADG,KAAK,IAAM,KAAK,aAAa,MAAM,GAAK,QAK3C,IAHO,EAChB,KAAK,aAAa,kBAAkB,GAAK,GAEpB,GACzB,CAGA,MAAM,SAAyB,CAC7B,IAAM,EAAa,KAAKA,GACxB,GAAI,CAAC,GAAY,MACf,MAAU,MAAM,oCAAoC,EAKtD,GAFA,MAAM,KAAKE,GAAc,EAAY,GAAM,gCAAgC,EAC3E,MAAM,KAAKC,GAAqB,CAAU,EACtC,CAAC,KAAKC,GAAqB,CAAU,GAAK,CAAC,EAAW,MACxD,MAAU,MAAM,oDAAoD,CAExE,CAIA,IAAsB,CAChB,SAAKT,GAET,MAAKA,GAAU,SAAS,cAAc,QAAQ,EAG9C,IAAK,IAAM,KAAQ,EAAmB,CACpC,IAAM,EAAQ,KAAK,aAAa,CAAI,EAChC,IAAU,MACZ,KAAKA,GAAQ,aAAa,EAAM,CAAK,CAEzC,CAEA,KAAKA,GAAQ,MAAM,OAAS,OAG5B,KAAKA,GAAQ,iBAAiB,WAAc,KAAK,KAAKC,GAAW,CAAC,EAElE,KAAK,YAAY,YAAY,KAAKD,EAAO,CAfK,CAgBhD,CAEA,KAAMU,GAAS,EAA0C,CACvD,IAAM,EAAgB,KAAKC,GACvB,GACF,MAAM,EAAc,UAAY,IAAA,EAAS,EAE3C,IAAM,EAAS,KAAKX,GACpB,GAAI,IAAsB,KAAKG,IAAgC,CAAC,GAAU,CAAC,KAAK,YAC9E,OAGF,IAAM,EAAU,KAAKS,GAAgB,EAAmB,CAAM,EAC9D,KAAKD,GAAqB,EAC1B,GAAI,CACF,MAAM,CACR,QAAU,CACJ,KAAKA,KAAuB,IAC9B,KAAKA,GAAqB,KAE9B,CACF,CAEA,KAAMC,GAAgB,EAA2B,EAA0C,CACzF,IAAI,EAEJ,GAAI,CACF,IAAM,EAAY,IAAI,EAAsB,CAC1C,SACA,aAAc,KAAKC,GAAiB,EACpC,UAAW,KAAK,aAAa,SAAS,GAAK,CAC7C,CAAC,EAIK,EAAc,CAAE,YAAa,GAAO,WAAY,EAAG,cAH7B,CACtB,GAAY,KAAKP,GAAgB,EAAY,gCAAgC,CACnF,CACkF,EAC5E,EAAS,IAAI,EACjB,CAAE,KAAM,aAAa,KAAK,IAAM,cAAe,QAAS,OAAQ,EAChE,CACE,mBAAoB,CAAE,KAAM,MAAO,EACnC,YAAa,CAAE,MAAO,EAAa,UAAW,EAAa,QAAS,CAAY,CAClF,CACF,EACM,EAAgC,CACpC,SACA,MAAO,GACP,gBAAiB,EACjB,aAAc,QAAQ,QAAQ,EAC9B,MAAO,EAAW,EAClB,kBAAmB,IAAI,IACvB,sBAAuB,IAAI,IAC3B,oBAAqB,IAAI,GAC3B,EAoBA,GAnBA,EAAa,EACb,KAAKD,GAAc,EACnB,EAAO,YAAgB,CACjB,EAAkB,OAAO,KAAUD,GAAY,CAAiB,CACtE,EACA,EAAO,QAAW,GAAU,CAC1B,KAAKU,GAAgB,EAAmB,EAAO,yBAAyB,CAC1E,EAEA,MAAM,EAAO,QAAQ,CAAS,EAE5B,IAAsB,KAAKX,IAC3B,CAAC,KAAKM,GAAqB,CAAiB,IAK9C,MAAM,KAAKF,GAAc,EAAmB,GAAO,mBAAmB,EACtE,MAAM,KAAKC,GAAqB,CAAiB,EAC7C,CAAC,KAAKC,GAAqB,CAAiB,GAAG,OACnD,EAAkB,MAAQ,GAC1B,KAAKM,GAAe,kBAAkB,CACxC,OAAS,EAAO,CACd,GACE,IAAsB,KAAKZ,IAC3B,CAAC,KAAK,aACL,GAAc,CAAC,KAAKM,GAAqB,CAAU,EAEpD,OAEE,EACF,KAAKK,GAAgB,EAAY,EAAO,mBAAmB,EAE3D,KAAKE,GAAe,EAAO,mBAAmB,CAElD,CACF,CAEA,KAAMC,GAAoB,EAAmC,CAC3D,IAAM,EAAe,EAAO,sBAAsB,EAC5C,CAAC,EAAO,EAAW,EAAmB,GAAW,MAAM,QAAQ,IAAI,CACvE,GAAc,MACV,EAAO,UAAU,IAAA,GAAW,CAAE,UAAW,SAAU,CAAC,EAAE,KAAM,GAAW,EAAO,KAAK,EACnF,CAAC,EACL,GAAc,UACV,EACG,cAAc,IAAA,GAAW,CAAE,UAAW,SAAU,CAAC,EACjD,KAAM,GAAW,EAAO,SAAS,EACpC,CAAC,EACL,GAAc,UACV,EACG,sBAAsB,IAAA,GAAW,CAAE,UAAW,SAAU,CAAC,EACzD,KAAM,GAAW,EAAO,iBAAiB,EAC5C,CAAC,EACL,GAAc,QACV,EAAO,YAAY,IAAA,GAAW,CAAE,UAAW,SAAU,CAAC,EAAE,KAAM,GAAW,EAAO,OAAO,EACvF,CAAC,CACP,CAAC,EACD,MAAO,CAAE,QAAO,YAAW,oBAAmB,SAAQ,CACxD,CAEA,GAAqB,EAAiC,CACpD,OAAO,KAAKZ,KAAgB,CAC9B,CAEA,GAAgB,EAAwB,EAAuB,CAC7D,KAAUE,GAAc,EAAY,GAAM,CAAO,EAAE,UAAY,IAAA,EAAS,CAC1E,CAEA,GAAc,EAAwB,EAAiB,EAAgC,CACrF,IAAM,EAAkB,EAAE,EAAW,gBACjC,EAAwB,GACtB,EAAU,EAAW,aACxB,UAAY,IAAA,EAAS,EACrB,KAAK,SAAY,CAChB,IAAM,MACJ,KAAKE,GAAqB,CAAU,GAAK,IAAoB,EAAW,gBACrE,KAAS,EAEd,IAAI,CACF,IAAM,EAAQ,MAAM,KAAKQ,GAAoB,EAAW,MAAM,EAC9D,GAAI,CAAC,EAAS,EAAG,OAEjB,KAAKC,GAAe,CAAU,EAC9B,EAAwB,GACxB,EAAW,MAAQ,EACnB,MAAM,KAAKC,GAA2B,EAAY,KAAK,WAAY,CAAQ,CAC7E,OAAS,EAAO,CACd,GAAI,CAAC,EAAS,EAAG,CACX,GAAuB,KAAKD,GAAe,CAAU,EACzD,MACF,CAEA,MADA,KAAKJ,GAAgB,EAAY,EAAO,CAAO,EACzC,CACR,CAEA,GAAI,CAAC,EAAS,EAAG,CACf,KAAKI,GAAe,CAAU,EAC9B,MACF,CACI,GAAU,EAAW,OAAO,KAAKH,GAAe,0BAA0B,CAN9E,CAOF,CAAC,EAEH,MADA,GAAW,aAAe,EACnB,CACT,CAEA,KAAMP,GAAqB,EAAuC,CAChE,KAAO,KAAKC,GAAqB,CAAU,GAAG,CAC5C,IAAM,EAAU,EAAW,aAE3B,GADA,MAAM,EACF,IAAY,EAAW,aAAc,MAC3C,CACF,CAEA,GAAe,EAA6D,CAC1E,KAAK,cACH,IAAI,YAAuC,EAAM,CAC/C,OAAQ,CACN,MAAO,KAAK,aACZ,UAAW,KAAK,iBAChB,QAAS,KAAK,cAChB,CACF,CAAC,CACH,CACF,CAEA,GAAe,EAAgB,EAAuB,CACpD,QAAQ,MAAM,eAAe,EAAQ,GAAI,CAAK,EAC9C,KAAK,cACH,IAAI,YAAuC,mBAAoB,CAAE,OAAQ,CAAE,OAAM,CAAE,CAAC,CACtF,CACF,CAEA,GAAgB,EAAwB,EAAgB,EAAuB,CACxE,KAAKW,GAAsB,CAAU,IAC1C,KAAKJ,GAAe,EAAO,CAAO,EAClC,KAAUK,GAAiB,CAAU,EACvC,CAEA,IAA2B,CACzB,IAAM,EAAW,KAAK,aAAa,eAAe,EAClD,GAAI,IAAa,KAAM,CACrB,GAAI,CAAC,EAAU,MAAU,MAAM,+BAA+B,EAC9D,OAAO,CACT,CAEA,GACE,KAAKrB,IAAS,aAAa,SAAS,GACpC,CAAC,KAAKA,GAAQ,QAAQ,SAAS,mBAAmB,EAElD,MAAU,MAAM,oDAAoD,EAEtE,GAAI,KAAK,aAAa,QAAQ,EAAG,OAAO,OAAO,SAAS,OAExD,IAAM,EAAM,KAAK,aAAa,KAAK,EACnC,GAAI,CAAC,EAAK,OAAO,OAAO,SAAS,OACjC,IAAM,EAAM,IAAI,IAAI,EAAK,OAAO,SAAS,IAAI,EAC7C,GAAI,EAAI,WAAa,SAAU,OAAO,OAAO,SAAS,OACtD,GAAI,EAAI,SAAW,OACjB,MAAU,MAAM,iDAAiD,EAEnE,OAAO,EAAI,MACb,CAEA,KAAMmB,GACJ,EACA,EACA,EACe,CACf,IAAM,EAAyC,SAAS,cAAgB,UAAU,aAClF,GAAI,CAAC,EACH,MAAU,MAAM,2CAA2C,EAG7D,GAAI,KAAKG,IAA0B,EAAkB,CAAY,EAAG,CAGlE,GADA,MAAM,EAAa,gBAAgB,EAC/B,CAAC,EAAS,EAAG,OACjB,KAAKA,GAAyB,EAChC,CAEA,MAAM,KAAKC,GAA6B,EAAY,EAAc,EAAQ,CAAQ,EAC7E,EAAS,IACV,EAA8B,CAAY,GAC5C,KAAKC,GAAiC,EAAY,EAAc,CAAM,EACtE,KAAKC,GAA+B,EAAY,EAAc,CAAM,IAEpE,EAAW,MAAM,UAAU,OAAS,GACpC,EAAW,MAAM,kBAAkB,OAAS,GAC5C,EAAW,MAAM,QAAQ,OAAS,IAElC,QAAQ,KACN,2FACF,EAEJ,CAEA,KAAMF,GACJ,EACA,EACA,EACA,EACe,CACf,IAAK,IAAM,KAAQ,EAAW,MAAM,MAAO,CACzC,GAAI,CAAC,EAAS,EAAG,OACjB,IAAM,EAAe,GAAG,IAAS,EAAK,OACtC,GAAI,EAAwB,EAAW,kBAAmB,EAAc,MAAM,EAAG,SAEjF,IAAM,EAEF,CACF,KAAM,EACN,GAAI,EAAK,QAAU,IAAA,IAAa,CAAE,MAAO,EAAK,KAAM,EACpD,YAAa,EAAK,aAAe,qBAAqB,EAAK,OAC3D,YAAa,EAAK,YAClB,GAAI,EAAK,aAAa,eAAiB,IAAA,IAAa,CAClD,YAAa,CAAE,aAAc,EAAK,YAAY,YAAa,CAC7D,EACA,QAAU,GAAS,KAAKG,GAAgB,EAAK,KAAM,CAAI,CACzD,EACM,EAAa,IAAI,gBACvB,EAAW,kBAAkB,IAAI,EAAc,CAAU,EACzD,GAAI,CACF,MAAM,EAAa,aAAa,EAAY,CAAE,OAAQ,EAAW,MAAO,CAAC,CAC3E,OAAS,EAAO,CACd,IAAM,EAAa,EAAW,OAAO,QAQrC,GAPK,IACH,KAAKJ,GAAyB,GAC9B,EAAW,MAAM,GAEf,EAAW,kBAAkB,IAAI,CAAY,IAAM,GACrD,EAAW,kBAAkB,OAAO,CAAY,EAE9C,CAAC,EAAY,MAAM,CACzB,CACF,CACF,CAEA,GACE,EACA,EACA,EACM,CACN,IAAK,IAAM,KAAY,EAAW,MAAM,UAAW,CACjD,IAAM,EAAY,EAAwB,EAAQ,EAAS,GAAG,EAC9D,GAAI,EAAwB,EAAW,sBAAuB,EAAW,UAAU,EACjF,SAEF,IAAM,EAAiC,CACrC,IAAK,EACL,KAAM,EAAS,KACf,GAAI,EAAS,cAAgB,IAAA,IAAa,CAAE,YAAa,EAAS,WAAY,EAC9E,GAAI,EAAS,WAAa,IAAA,IAAa,CAAE,SAAU,EAAS,QAAS,EACrE,MAAO,EAAM,IAAY,KAAKK,GAAoB,EAAS,GAAG,CAChE,EACM,EAAe,EAAa,iBAAiB,CAAU,EAC7D,EAAW,sBAAsB,IAAI,EAAW,CAAY,CAC9D,CAEA,IAAK,IAAM,KAAoB,EAAW,MAAM,kBAAmB,CACjE,IAAM,EAAgB,IAAI,EAAY,EAAiB,WAAW,EAC5D,EAAY,EAChB,EACA,EAAiB,YACjB,EAAc,aAChB,EACA,GAAI,EAAwB,EAAW,sBAAuB,EAAW,UAAU,EACjF,SAEF,IAAM,EAAiC,CACrC,IAAK,EACL,KAAM,EAAiB,KACvB,GAAI,EAAiB,cAAgB,IAAA,IAAa,CAChD,YAAa,EAAiB,WAChC,EACA,GAAI,EAAiB,WAAa,IAAA,IAAa,CAAE,SAAU,EAAiB,QAAS,EACrF,MAAO,EAAM,IACX,KAAKA,GAAoB,EAAc,OAAO,EAAwB,GAAU,CAAC,CAAC,CAAC,CAAC,CACxF,EACM,EAAe,EAAa,iBAAiB,CAAU,EAC7D,EAAW,sBAAsB,IAAI,EAAW,CAAY,CAC9D,CACF,CAEA,GACE,EACA,EACA,EACM,CACN,IAAK,IAAM,KAAU,EAAW,MAAM,QAAS,CAC7C,IAAM,EAAe,GAAG,IAAS,EAAO,OACxC,GAAI,EAAwB,EAAW,oBAAqB,EAAc,QAAQ,EAAG,SAErF,IAAM,EAA+B,CACnC,KAAM,EACN,GAAI,EAAO,cAAgB,IAAA,IAAa,CAAE,YAAa,EAAO,WAAY,EAC1E,GAAI,EAAO,WACT,EAAO,UAAU,OAAS,GAAK,CAC7B,WAAY,CACV,KAAM,SACN,WAAY,OAAO,YACjB,EAAO,UAAU,IAAK,GAAQ,CAC5B,EAAI,KACJ,CACE,KAAM,SACN,GAAI,EAAI,cAAgB,IAAA,IAAa,CAAE,YAAa,EAAI,WAAY,CACtE,CACF,CAAC,CACH,EACA,SAAU,EAAO,UAAU,OAAQ,GAAM,EAAE,QAAQ,EAAE,IAAK,GAAM,EAAE,IAAI,CACxE,CACF,EACF,IAAM,GAAS,KAAKC,GAAiB,EAAO,KAAM,CAAI,CACxD,EACM,EAAe,EAAa,eAAe,CAAU,EAC3D,EAAW,oBAAoB,IAAI,EAAc,CAAY,CAC/D,CACF,CAEA,GAAe,EAA8B,CAC3C,IAAM,EAAQ,CAAC,GAAG,EAAW,kBAAkB,OAAO,CAAC,EACjD,EAAgB,CACpB,GAAG,EAAW,sBAAsB,OAAO,EAC3C,GAAG,EAAW,oBAAoB,OAAO,CAC3C,EACA,EAAW,kBAAkB,MAAM,EACnC,EAAW,sBAAsB,MAAM,EACvC,EAAW,oBAAoB,MAAM,EACrC,EAAW,MAAQ,EAAW,EAC1B,EAAM,OAAS,IAAG,KAAKN,GAAyB,IAEpD,IAAK,IAAM,KAAc,EACvB,GAAI,CACF,EAAW,MAAM,CACnB,OAAS,EAAO,CACd,QAAQ,KAAK,kDAAmD,CAAK,CACvE,CAEF,IAAK,IAAM,KAAgB,EACzB,GAAI,CACF,EAAa,WAAW,CAC1B,OAAS,EAAO,CACd,QAAQ,KAAK,kDAAmD,CAAK,CACvE,CAEJ,CAEA,IAAyB,CACvB,IAAM,EAAa,KAAKjB,GACxB,GAAI,CAAC,GAAY,MACf,MAAU,MAAM,oCAAoC,EAEtD,OAAO,EAAW,MACpB,CAEA,IAA0B,CACxB,IAAM,EAAU,OAAO,KAAK,aAAa,cAAc,CAAC,EACxD,OAAO,OAAO,cAAc,CAAO,GAAK,EAAU,EAAI,EAAU,CAClE,CAEA,KAAMqB,GAAgB,EAAkB,EAAwD,CAC9F,OAAO,KAAKG,GAAe,EAAE,SAC3B,CAAE,KAAM,EAAU,UAAW,CAAK,EAClC,CAAE,QAAS,KAAKC,GAAgB,CAAE,CACpC,CACF,CAEA,KAAMH,GAAoB,EAA0C,CAClE,OAAO,KAAKE,GAAe,EAAE,aAAa,CAAE,KAAI,EAAG,CAAE,QAAS,KAAKC,GAAgB,CAAE,CAAC,CACxF,CAEA,KAAMF,GAAiB,EAAc,EAAwD,CAC3F,OAAO,KAAKC,GAAe,EAAE,UAC3B,CAAE,OAAM,UAAW,CAAK,EACxB,CAAE,QAAS,KAAKC,GAAgB,CAAE,CACpC,CACF,CAEA,KAAM7B,IAA4B,CAChC,IAAM,EAAoB,EAAE,KAAKE,GACjC,MAAM,KAAKC,GAAY,EACnB,MAAsB,KAAKD,IAAgC,CAAC,KAAK,cACrE,MAAM,KAAKO,GAAS,CAAiB,CACvC,CAEA,KAAMN,GAAY,EAAa,KAAKC,GAA4B,CAC1D,CAAC,GAAc,CAAC,KAAKe,GAAsB,CAAU,GACzD,MAAM,KAAKC,GAAiB,CAAU,CACxC,CAEA,GAAsB,EAAiC,CAQrD,OAPK,KAAKZ,GAAqB,CAAU,GACzC,KAAKJ,GAAc,KACnB,EAAE,EAAW,gBACb,EAAW,MAAQ,GACnB,OAAO,EAAW,OAAO,QACzB,OAAO,EAAW,OAAO,QACzB,KAAKa,GAAe,CAAU,EACvB,IAP4C,EAQrD,CAEA,KAAMG,GAAiB,EAAuC,CAC5D,GAAI,CACF,MAAM,EAAW,OAAO,MAAM,CAChC,OAAS,EAAO,CACd,QAAQ,KAAK,6DAA8D,CAAK,CAClF,CACF,CACF,EASA,SAAgB,EAAyB,EAAU,aAAoB,CACjE,OAAO,eAAmB,KAAe,CAAC,eAAe,IAAI,CAAO,GACtE,eAAe,OAAO,EAAS,CAAgB,CAEnD"}
package/dist/element.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as registerMCPIframeElement, i as MCPIframeItemsEventDetail, n as MCPIframeErrorEventDetail, r as MCPIframeEventMap, t as MCPIframeElement } from "./MCPIframeElement-d12Xcjs_.js";
1
+ import { a as registerMCPIframeElement, i as MCPIframeItemsEventDetail, n as MCPIframeErrorEventDetail, r as MCPIframeEventMap, t as MCPIframeElement } from "./MCPIframeElement-Br8JNWm_.js";
2
2
  export { MCPIframeElement, type MCPIframeErrorEventDetail, type MCPIframeEventMap, type MCPIframeItemsEventDetail, registerMCPIframeElement };
package/dist/element.js CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./MCPIframeElement-BbBz_xpV.js";export{t as MCPIframeElement,e as registerMCPIframeElement};
1
+ import{n as e,t}from"./MCPIframeElement-CYns0bdY.js";export{t as MCPIframeElement,e as registerMCPIframeElement};
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as MCPIframeItemsEventDetail, n as MCPIframeErrorEventDetail, r as MCPIframeEventMap, t as MCPIframeElement } from "./MCPIframeElement-d12Xcjs_.js";
1
+ import { i as MCPIframeItemsEventDetail, n as MCPIframeErrorEventDetail, r as MCPIframeEventMap, t as MCPIframeElement } from "./MCPIframeElement-Br8JNWm_.js";
2
2
  export { MCPIframeElement, type MCPIframeErrorEventDetail, type MCPIframeEventMap, type MCPIframeItemsEventDetail };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{n as e,t}from"./MCPIframeElement-BbBz_xpV.js";e();export{t as MCPIframeElement};
1
+ import{n as e,t}from"./MCPIframeElement-CYns0bdY.js";e();export{t as MCPIframeElement};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @mcp-b/mcp-iframe\n *\n * Custom element for exposing iframe MCP tools, resources, and prompts\n * to the parent page's Model Context API.\n *\n * @example\n * ```typescript\n * // Import to auto-register the <mcp-iframe> element\n * import '@mcp-b/mcp-iframe';\n *\n * // Or use the side-effect-free entry for a custom tag\n * import { registerMCPIframeElement } from '@mcp-b/mcp-iframe/element';\n * registerMCPIframeElement('custom-mcp-iframe');\n * ```\n *\n * @example\n * ```html\n * <mcp-iframe src=\"./child-app.html\" id=\"my-app\"></mcp-iframe>\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerMCPIframeElement } from './MCPIframeElement.js';\n\nexport {\n MCPIframeElement,\n type MCPIframeErrorEventDetail,\n type MCPIframeEventMap,\n type MCPIframeItemsEventDetail,\n} from './MCPIframeElement.js';\n\nregisterMCPIframeElement();\n"],"mappings":"qDAiCA,GAA0B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @mcp-b/mcp-iframe\n *\n * Custom element for exposing iframe MCP tools, resources, and prompts\n * to the parent page's Model Context API.\n *\n * @example\n * ```typescript\n * // Import to auto-register the <mcp-iframe> element\n * import '@mcp-b/mcp-iframe';\n *\n * // Or use the side-effect-free entry for a custom tag\n * import { registerMCPIframeElement } from '@mcp-b/mcp-iframe/element';\n * registerMCPIframeElement('custom-mcp-iframe');\n * ```\n *\n * @example\n * ```html\n * <mcp-iframe src=\"./child-app.html\" id=\"my-app\"></mcp-iframe>\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerMCPIframeElement } from './MCPIframeElement.js';\n\nexport {\n MCPIframeElement,\n type MCPIframeErrorEventDetail,\n type MCPIframeEventMap,\n type MCPIframeItemsEventDetail,\n} from './MCPIframeElement.js';\n\nregisterMCPIframeElement();\n"],"mappings":"qDAiCA,EAAyB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/mcp-iframe",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "description": "Custom element for exposing iframe MCP tools, resources, and prompts to parent page",
5
5
  "keywords": [
6
6
  "browser",
@@ -50,14 +50,14 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@modelcontextprotocol/client": "2.0.0",
53
- "@mcp-b/transports": "5.0.1"
53
+ "@mcp-b/transports": "5.1.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "22.17.2",
56
+ "@types/node": "22.20.1",
57
57
  "typescript": "^5.8.3",
58
- "vite-plus": "^0.1.22",
59
- "@mcp-b/webmcp-types": "5.0.1",
60
- "@mcp-b/webmcp-ts-sdk": "5.0.1"
58
+ "vite-plus": "0.1.24",
59
+ "@mcp-b/webmcp-ts-sdk": "5.1.0",
60
+ "@mcp-b/webmcp-types": "5.1.0"
61
61
  },
62
62
  "engines": {
63
63
  "node": ">=20"