Skip to main content
A Web Component that wraps an iframe and bridges its MCP tools, resources, and prompts to the parent page’s navigator.modelContext. Items from the iframe are namespaced with the element’s id to prevent collisions.

Installation

pnpm add @mcp-b/mcp-iframe @modelcontextprotocol/sdk
The iframe page must have @mcp-b/global (or any navigator.modelContext implementation) installed.

Minimal example

Usage

<mcp-iframe src="./child-app.html" id="my-app"></mcp-iframe>

<script type="module">
  import '@mcp-b/mcp-iframe';

  const el = document.querySelector('mcp-iframe');
  el.addEventListener('mcp-iframe-ready', (e) => {
    console.log('Exposed tools:', e.detail.tools);
    // e.g. ["my-app_calculate", "my-app_get_data"]
  });
</script>
Importing @mcp-b/mcp-iframe auto-registers the <mcp-iframe> custom element. No additional setup is required.

Attributes

AttributeTypeDefaultDescription
srcstringURL of the iframe page.
idstring"iframe"Used as the tool name prefix. Sanitized to match [a-zA-Z0-9_-].
target-originstringInferred from srcOverride the postMessage target origin. If omitted, the origin is extracted from the src URL.
channelstring"mcp-iframe"Channel ID for the underlying IframeParentTransport.
call-timeoutnumber30000Timeout in milliseconds for tool calls, resource reads, and prompt gets.
prefix-separatorstring"_"Separator between the prefix and the item name. Must contain only [a-zA-Z0-9_-] characters.
Standard iframe attributes (sandbox, allow, width, height, loading, referrerpolicy, name, srcdoc, allowfullscreen, credentialless) are mirrored to the internal <iframe> element.

Events

EventDetail typeFired when
mcp-iframe-ready{ tools: string[], resources: string[], prompts: string[] }The element connects to the iframe’s MCP server and registers all items on the parent.
mcp-iframe-error{ error: unknown }Connection to the iframe’s MCP server fails.
mcp-iframe-tools-changed{ tools: string[], resources: string[], prompts: string[] }Items are refreshed via the refresh() method.
All tools, resources, and prompts arrays contain the prefixed names as registered on the parent.

Name prefixing

Tools and prompts from the iframe are registered on the parent as {id}{separator}{name}:
Iframe tool nameElement idSeparatorParent tool name
calculatemy-app_ (default)my-app_calculate
get_databilling_billing_get_data
helpassistant-assistant-help
Prefixed names must match the MCP name pattern ^[a-zA-Z0-9_-]{1,128}$. Names that exceed 128 characters or contain invalid characters are skipped with a console error. Resource URIs are prefixed the same way: a resource config://settings in an iframe with id="my-app" becomes my-app_config://settings on the parent.

Properties

PropertyTypeDescription
iframeHTMLIFrameElement | nullThe wrapped iframe element.
clientClient | nullThe MCP client connected to the iframe’s server.
readybooleanWhether the element is connected to the iframe’s MCP server.
exposedToolsstring[]Prefixed tool names registered on the parent.
exposedResourcesstring[]Prefixed resource URIs registered on the parent.
exposedPromptsstring[]Prefixed prompt names registered on the parent.
mcpToolsTool[]Raw tools from the iframe (without prefix).
mcpResourcesResource[]Raw resources from the iframe (without prefix).
mcpPromptsPrompt[]Raw prompts from the iframe (without prefix).
itemPrefixstringThe computed prefix string ({id}{separator}).

Methods

MethodReturnsDescription
refresh()Promise<void>Re-fetches all tools, resources, and prompts from the iframe, unregisters the old items, and registers the new ones. Fires mcp-iframe-tools-changed on completion.

Programmatic registration

To register the custom element with a different tag name:
import { registerMCPIframeElement } from '@mcp-b/mcp-iframe';

registerMCPIframeElement('my-mcp-frame');
If you import @mcp-b/mcp-iframe without calling registerMCPIframeElement, the element is auto-registered as <mcp-iframe> in browser environments.

Lifecycle

  1. On connectedCallback, the element creates an internal <iframe> and mirrors attributes.
  2. When the iframe fires its load event, the element creates an IframeParentTransport and an MCP Client, then connects.
  3. On successful connection, tools, resources, and prompts are fetched from the iframe’s MCP server.
  4. Each item is registered on the parent’s navigator.modelContext with the element’s prefix.
  5. The mcp-iframe-ready event fires.
  6. On disconnectedCallback, all registered items are unregistered and the client and transport are closed.
Changing src, srcdoc, target-origin, or channel while connected triggers a reconnection cycle.