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.
Requirements
Section titled “Requirements”- 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-testingflag), or Edge 150+. - An HTTPS page. WebMCP is a secure context, and the document must be origin-isolated (it rejects if
document.domainhas been set). If your page is inside an iframe, the frame needsallow="tools".
Step 1: Make the container public
Section titled “Step 1: Make the container public”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.
Step 2: Mint a publishable key
Section titled “Step 2: Mint a publishable key”- With the container set to public, the Embed row appears in Settings below Public Access. Click Manage Embed.
- Click Create Embed Key.
- Optionally name the key (e.g. “Marketing site”).
- 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. - 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.
Step 3: Drop the snippet
Section titled “Step 3: Drop the snippet”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:
- Reads
data-keyand validates the format. - Resolves
document.modelContext(falling back tonavigator.modelContextfor browsers that shipped before the May 2026 rename). If neither exists, logs a hint and exits. - Fetches
/v1/embed/toolsfrom the Wire API to load the schemas your key is scoped to. - Calls
modelContext.registerToolfor each one, with a singleAbortControllersignal so all tools can be unregistered together —AbortSignalis 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.
Verify it works
Section titled “Verify it works”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:
- Install the extension from the Chrome Web Store.
- In
chrome://flags, enable WebMCP for testing (#enable-webmcp-testing) so the API is available without an origin-trial token. - Restart Chrome.
- Open the page where you embedded Wire’s
<script>and click the Inspector’s toolbar icon. - 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.
Tool surface
Section titled “Tool surface”Embed keys are read-only by design. The public endpoints expose three tools:
| Tool | Purpose |
|---|---|
wire_explore | Browse the container: its shape (entities, objects, files) and the entries in it, or one entry by id. |
wire_search | Fuzzy retrieval over raw content (file chunks, agent writes). Use for natural-language questions. |
wire_navigate | Traverse 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.
Multiple containers on one page
Section titled “Multiple containers on one page”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_abc1wire_explore__pk_live_def2Origin allowlist
Section titled “Origin allowlist”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.
Rate limits and credit ceiling
Section titled “Rate limits and credit ceiling”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.
Revoking a key
Section titled “Revoking a key”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.
Security model
Section titled “Security model”Embed keys are publishable on purpose: they live in client HTML on third-party sites. The defense in depth is:
- The key only works when the parent container is
public. - The origin allowlist enforces the key only runs on pages you authorize.
- The read-only tool surface means a leaked key cannot mutate your container.
- Per-key rate limits and credit ceilings cap blast radius if the key is misused.
Troubleshooting
Section titled “Troubleshooting”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.
Limits
Section titled “Limits”- 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.