Catalog

This is not the latest version.

Viewing v1.0, published September 3, 2026.

Go to Latest Version

BuilderIO

webmcp v1.0

as of v1.0latest is B

Open a user-provided URL in the host's built-in browser and use the page's MCP or WebMCP tools before browser UI automation for app communication or edits.

NewPublished September 3, 2026all versions

Byte-exact. Everything on this page is exactly what v1.0 published, including every file.

What changedInitial version — nothing to compare.

WebMCP

Use /webmcp <url> [request] when the user wants to open or operate a web app. The first token is the URL and the remaining text is the request to complete in that same browser session. For example:

/webmcp slides.agent-native.com make me a new deck about customer onboarding

Keep working through the request after opening the page. Do not stop after navigation when the user supplied an operation.

Open the requested URL

  • Accept a full URL or hostname. If the scheme is omitted, prepend https://; preserve the host, path, query, and hash exactly. Never guess beta or production variants or replace the request with an external browser.
  • The browser target is part of this skill: use the host's built-in or in-app browser, never a normal Chrome/Edge tab or browser-extension session. A matching URL in an external browser does not satisfy the request.
  • Reuse an existing matching tab only when it belongs to the built-in browser. Otherwise create a new built-in tab for the exact URL, make it visible, and keep it open as the requested deliverable. In Codex CUA, use the iab browser (cua.getTab(tabId, { browser: "iab" }) or cua.createBrowserTab("iab", url, { visible: true })), never browser: "chrome" for /webmcp.
  • Read the page after it loads. Opening the URL is enough if no operation follows.

Handle sign-in before tool work

After opening the page, check whether it is signed out or shows an auth-required state before attempting a mutation. If it needs sign-in:

  • Leave the same built-in browser tab open.
  • Tell the user: Please sign in in the open browser, then reply "continue".
  • Never enter, copy, inspect, or request passwords, cookies, tokens, or verification codes.

When the user replies, read the page again and rediscover tools. Do not reuse tool descriptors or a failed result from before authentication.

Find and use page tools through the host

After navigation and authentication, make one bounded discovery pass. A host bridge is useful only when its list and run tools are actually exposed to the agent. Do not treat a capability wrapper, a manifest, or a failed fetchTools() helper as the page's WebMCP surface.

  • If the host exposes a browser-session or host WebMCP bridge, call its listed list tool once, then its matching run tool with the exact discovered name, origin, and args.
  • If the host exposes MCP-B relay tools, call the listed source/tool discovery tool once and use the exact dynamic tool returned for the requested tab.
  • Otherwise use the host's live-page JavaScript evaluator immediately. In Codex CUA, use tab.capabilities.get("cdp") and CDP Runtime.evaluate first so the expression runs in the page world where host-injected globals live. In Cowork, use its equivalent same-world page evaluator. Use tab.playwright.evaluate only as a fallback because Playwright may run in an isolated world that cannot see document.modelContext. Do not open or type into a developer console.
  • Do not substitute a generic tool-search, unrelated app connector, ask_app, or remote API for the current tab's page tools unless the host explicitly binds it to that browser session.

For a direct page call, keep listing and execution in the same page context so the host never tries to serialize or call a page-owned callback. In Codex CUA, the CDP response is nested, so explicitly surface its serializable value:

const cdp = await tab.capabilities.get("cdp");
const response = await cdp.send("Runtime.evaluate", {
  expression: `(async () => {
    const context = document.modelContext;
    if (!context) return JSON.stringify({ state: "absent", href: location.href });
    const tools = await context.getTools();
    const tool = tools.find(({ name }) => name === TOOL_NAME);
    if (!tool) return JSON.stringify({ state: "tool-missing", toolCount: tools.length, tools });
    const result = await context.executeTool(tool, JSON.stringify(ARGS));
    return JSON.stringify({
      state: "executed",
      result: typeof result === "string" ? JSON.parse(result) : result,
    });
  })()`,
  awaitPromise: true,
  returnByValue: true,
});
const raw = response?.result?.value;
nodeRepl.write(
  JSON.stringify({
    webmcpResult:
      typeof raw === "string" ? JSON.parse(raw) : { state: "unreadable" },
  }),
);

Replace TOOL_NAME and ARGS with the exact listed name and schema-shaped arguments. document.modelContext is the canonical page API; navigator.modelContext is deprecated. The framework's WebMCP surface accepts the schema-shaped input as a JSON string. The descriptor is not a callable run() function, so do not copy it out of the page and invoke it from the host.

In Codex CUA, an evaluator response may prepend the tab's accessibility tree or other observations and append the explicit returned value after that block. Read through the end of the output and parse response.result.value or the explicit webmcpResult payload from nodeRepl.write (or the host's equivalent result channel). Treat the AX tree, screenshots, and other observations as context only. A value you cannot find is unread, not absent. A Playwright null or missing document.modelContext is indeterminate because its isolated world may hide the host surface. Confirm it with CDP or a second same-world evaluator before declaring WebMCP unsupported. If the second evaluator is unavailable, report the evaluator as unavailable, not unsupported. A confirmed empty list means the page advertised WebMCP but exposed no tools.

The controlled Codex CUA A/B on the beta Slides page showed the reason: the Playwright evaluator returned supported:false, while the same-page CDP evaluator returned state:"supported", toolCount:136, and create-deck with its schema. Use the page-world result at the end of the evaluator output.

Do not probe hidden globals, guess alternate method signatures, or retry the same unavailable surface. Allow at most one fresh discovery after the user signs in or the page navigates.

The ChatGPT app's page-world document.modelContext may expose codexExecuteTool, codexGetTools, executeTool, getTools, and registerTool; these can all have length === 0, so do not infer their signatures from arity. Its executeTool expects the tool descriptor followed by JSON.stringify(args), not an object.

After discovery:

  1. For any state-dependent operation, call the page's current-screen or context read first. Use the exact IDs and selection metadata returned there.
  2. Call the smallest named MCP mutation that satisfies the request. Inspect the discovered input schema for operation variants before concluding that a capability is missing; a composite action may own the exact operation (for example, Slides patch-deck accepts a delete-slide operation). Keep unrelated content untouched.
  3. Read the result back with the appropriate MCP read tool and only then report success.

List immediately before execution because page tools can change after navigation, authentication, and selection changes. With JavaScript evaluation, call getTools() immediately before executeTool() in the same evaluation.

Do not click, double-click, type, drag, or use browser DOM automation to perform an app operation when a matching MCP tool is available. UI controls may be used for navigation, visual inspection, and actions with no MCP equivalent.

Slides generation workflow

For Agent-Native Slides, /webmcp slides.agent-native.com <request> should use the discovered action tools. For a new generated deck:

  1. Call get-workspace-defaults when it is available and no reference deck or design system was named.
  2. Call create-deck with slides: [] or omit slides. It persists an empty editable deck, returns its id, and sends a navigation command to open it.
  3. If the connected tab did not move, call navigate with that deck id.
  4. Call add-slide once per slide in order and wait for each result. Read the deck back with get-deck before reporting completion.

Use a non-empty create-deck payload only for imports or an intentional atomic bulk replacement. The empty-deck workflow lets the user watch the deck grow without one long, fragile tool call.

For source-preserving Slides decks, read get-deck.sourceEditability before structural edits. If the user explicitly asks to rewrite the imported deck, pass rewriteSource: true to patch-deck; this conversion clears source-preservation metadata, so do not use it merely to bypass a blocked delete or reorder.

MCP unavailable

If neither host bridge nor a matching direct app MCP tool is actually available after the bounded evaluator confirmation, stop before any state-changing UI action. Say whether the page advertised MCP and which host capability is missing. Never fall back to click, type, drag, or keyboard automation from /webmcp; only an explicit request to use UI automation for this specific operation changes that. In particular, a missing exact verb is not permission to click when a discovered composite action can express it, and a generic reply to continue is not permission to switch to UI automation. Do not silently treat a tool-list failure, manifest fetch, tool acknowledgment, or queued task as proof that an edit completed.

For Slides, delete slides through the discovered patch-deck action with operations: [{ op: "delete-slide", slideId: "..." }] after reading stable slide IDs. There is no need for a separate delete-slide tool or a keyboard shortcut.

Keep this failure fast. Do not spend more than one discovery pass and one independent evaluator confirmation trying unsupported capability names or invocation signatures, and do not loop on console, DOM, CDP, or hidden-global probes.

Do not hand-build raw authenticated HTTP requests as a substitute for a host-provided MCP tool. If the page requires sign-in, keep authentication in the built-in browser. Never copy credentials, cookies, tokens, or codes into prompts or tool inputs; let the user complete any required sign-in or approval.

Example

/webmcp slides.agent-native.com make me a new deck about customer onboarding opens https://slides.agent-native.com in the built-in browser, waits for the user to sign in if needed, discovers the live page tools, creates an empty deck, and adds slides one at a time. For a focused edit, inspect the current screen, use the smallest supported slide-edit action, and read the slide back. Do not double-click the canvas and type replacement text.

Command Palette

Search for a command to run...