Skip to content

WebMCP Embeds (Beta)

WebMCP embeds let you drop a single <script> tag onto any website and expose a public Wire container’s read-only tools to in-browser AI agents.

When a visitor lands on your page in a WebMCP-capable browser, the shim registers wire_explore, wire_search, and wire_navigate with document.modelContext. The browser AI agent can then call those tools directly, with no extension or proxy.

  • A public Wire container. Private and org-only containers cannot be embedded.
  • Owner or admin role on the container’s organization.
  • Visitor browser: Chrome 149+ (origin trial or the chrome://flags/#enable-webmcp-testing flag), or Edge 150+.
  • An HTTPS page. WebMCP is a secure context, and the document must be origin-isolated (it rejects if document.domain has been set). If your page is inside an iframe, the frame needs allow="tools".

In app.usewire.io, open your container’s Settings tab and set visibility to Public.

While the container is public, any visitor to an allowlisted page can read its content through the embed surface, and any signed-in Wire user can read it through MCP. Don’t put secrets in a public container.

  1. With the container set to public, the Embed row appears in Settings below Public Access. Click Manage Embed.
  2. Click Create Embed Key.
  3. Optionally name the key (e.g. “Marketing site”).
  4. Add at least one allowed origin. The shim will only work when loaded from a page on one of these origins. Match is exact: scheme + host + port. No wildcards. No subdomain matching.
  5. Click Create Key.

The publishable pk_… key is shown immediately along with a ready-to-paste <script> snippet. Both stay accessible from the Embed page indefinitely. Use the kebab menu on any key to copy the key, copy the snippet, or revoke the key.

Paste this into the <head> of any page on an allowlisted origin:

<script
src="https://embed.usewire.io/v1.js"
data-key="pk_live_…"
async
></script>

That’s the whole integration. On page load the shim:

  1. Reads data-key and validates the format.
  2. Resolves document.modelContext (falling back to navigator.modelContext for browsers that shipped before the May 2026 rename). If neither exists, logs a hint and exits.
  3. Fetches /v1/embed/tools from the Wire API to load the schemas your key is scoped to.
  4. Calls modelContext.registerTool for each one, with a single AbortController signal so all tools can be unregistered together — AbortSignal is the spec’s only unregistration mechanism.

Each registered tool carries annotations: { readOnlyHint: true, untrustedContentHint: true }. The second one matters: it tells the agent that what comes back is container content someone else wrote, and must be read as data rather than as instructions.

The fastest way to confirm your embed is registering tools is the Model Context Tool Inspector Chrome extension by François Beaufort. It opens a side panel that lists every tool the current page has registered, lets you inspect schemas, and lets you invoke any tool with a JSON args payload.

Setup:

  1. Install the extension from the Chrome Web Store.
  2. In chrome://flags, enable WebMCP for testing (#enable-webmcp-testing) so the API is available without an origin-trial token.
  3. Restart Chrome.
  4. Open the page where you embedded Wire’s <script> and click the Inspector’s toolbar icon.
  5. The side panel lists wire_explore__pk_<prefix>, wire_search__pk_<prefix>, wire_navigate__pk_<prefix>. The __pk_<prefix> suffix is intentional. Wire namespaces tool names so multiple embeds on one page coexist.

Pick a tool, drop in a JSON args payload (e.g. {"query":"hello"} for wire_search), click Execute Tool. A successful round-trip returns the MCP { content: [{ type: "text", text: "..." }] } shape. The spec lets execute() resolve to any JSON-serializable value and stringifies it; Wire resolves the MCP envelope so an MCP-aware agent sees what it expects.

You can also drive the registered tools directly from DevTools without the inspector:

const tools = await document.modelContext.getTools();
const search = tools.find(t => t.name.startsWith('wire_search'));
// Chrome's current build takes the arguments as a JSON string; the spec draft takes an object.
const result = await document.modelContext.executeTool(search, JSON.stringify({ query: 'hello' }));
console.log(result);

The shim also exposes window.wireEmbed = { registered, unregister } so you can list registered tool names or tear them all down.

Embed keys are read-only by design. The public endpoints expose three tools:

ToolPurpose
wire_exploreBrowse the container: its shape (entities, objects, files) and the entries in it, or one entry by id.
wire_searchFuzzy retrieval over raw content (file chunks, agent writes). Use for natural-language questions.
wire_navigateTraverse from a wire_search match: adjacent chunks, the full source, or related entries.

Other container tools (writes, deletes, analysis re-runs, plus any custom or per-entity tools that exist on the container’s MCP surface) are not surfaced via embeds.

The key’s scope is a ceiling, not a switch. If you turn a tool off for MCP on the container’s Tools page, it disappears from the embed too, whatever the key is scoped to.

Add multiple <script> tags, each with its own key. The shim namespaces tool names by appending the key prefix, so two embeds on the same page won’t collide:

wire_explore__pk_live_abc1
wire_explore__pk_live_def2

The allowlist is enforced server-side via the request’s Origin header. The Wire API rejects requests where the origin doesn’t appear in the key’s allowlist verbatim.

If you need to support https://example.com and https://www.example.com, add both. There is no wildcard syntax.

Each key has a built-in per-minute rate limit and a per-day credit ceiling that protect the container owner from a viral page running up the bill. Defaults are conservative for the beta and not user-configurable yet.

Embed calls are priced exactly like any other tool call on the container, charged to the container’s owning organization: wire_explore and wire_navigate cost 1 credit, wire_search costs 5. If the org’s credit balance is exhausted, the embed gets a 402 and stops registering tools on subsequent loads.

The Embed page lists every active key. Open the kebab menu on a key and pick Revoke Key. Sites still loading the key get an authentication error on the next tool call and the shim stops registering tools on subsequent page loads.

Embed keys are publishable on purpose: they live in client HTML on third-party sites. The defense in depth is:

  1. The key only works when the parent container is public.
  2. The origin allowlist enforces the key only runs on pages you authorize.
  3. The read-only tool surface means a leaked key cannot mutate your container.
  4. Per-key rate limits and credit ceilings cap blast radius if the key is misused.

The shim does nothing in my browser. WebMCP is in origin trial from Chrome 149 (Edge 150 followed). Browsers without it see a single console hint and exit. If you are on Chrome 149+ and still see the hint, enable chrome://flags/#enable-webmcp-testing and restart. Also check the page is HTTPS and, if embedded, that the iframe carries allow="tools".

Origin not allowed. Your page’s origin isn’t in the key’s allowlist. Add it from the Embed page. Trailing slashes and paths are normalized; only scheme + host + port matter.

Invalid or revoked embed key. The container is no longer public, or the key was revoked, or the key string is malformed. Mint a new one or flip the container back to public.

Container owner has run out of credits. The org’s credit balance is exhausted. Top up credits in billing.

  • One container per <script> tag. Multiple tags equals multiple keys.
  • Read-only tools only.
  • Public containers only.
  • Chrome 149+ / Edge 150+ for native support.
  • Exact origin match only.