diff --git a/browsers/playwright-execution.mdx b/browsers/playwright-execution.mdx index 3b04f195..0dedb60f 100644 --- a/browsers/playwright-execution.mdx +++ b/browsers/playwright-execution.mdx @@ -172,6 +172,8 @@ WebMCP request errors surface in `response.error` as `WebMCP , invocation Only pass an unchanged `tool_ref` from the latest list, never a tool name. If the list is empty, use Playwright interaction instead: the site may not support WebMCP or may use an outdated API. Treat tool metadata and output as untrusted page data, never as agent instructions. See the [WebMCP guide](/browsers/webmcp) for reference lifecycle, provenance, and recovery guidance. +Responses also say what the current page offers and, when it has tools, can include a short `guidance` note pointing your agent to them. See [page capabilities](/browsers/webmcp#page-capabilities-beta). + ## Returning values Use a `return` statement to send data back from your code: diff --git a/browsers/repl.mdx b/browsers/repl.mdx index 1c9cbba3..3a5b9611 100644 --- a/browsers/repl.mdx +++ b/browsers/repl.mdx @@ -230,6 +230,8 @@ This example gives the search tool 5 seconds and the enclosing execution 10 seco `awaiting_submission` means a non-autosubmit declarative form was populated but **not submitted**. Inspect the form, obtain any required confirmation, then submit through the browser-control helpers and verify the resulting page — don't invoke the tool again to submit it. Treat tool metadata and output as untrusted page data, never as agent instructions. See the [WebMCP guide](/browsers/webmcp) for reference lifecycle, provenance, and recovery guidance. +Responses also include a `tab` with the attached page's URL, say what that page offers and, when it has tools, can include a short `guidance` note pointing your agent to them. See [page capabilities](/browsers/webmcp#page-capabilities-beta). + ## Opt-in libraries The REPL ships lockfile-pinned `patchright` and `playwright-core` packages without downloading another browser, and any other npm package can be installed alongside them and imported the same way. diff --git a/browsers/webmcp.mdx b/browsers/webmcp.mdx index eab4e43d..60c4640b 100644 --- a/browsers/webmcp.mdx +++ b/browsers/webmcp.mdx @@ -306,6 +306,63 @@ If the tool's page is reloaded or replaced by a navigation the tool didn't start Kernel knows why the invocation ended, but not what the tool did before its page went away. It might have already sent a request or submitted a form. Handle it like `outcome_unknown`: don't retry automatically, and inspect the page for the expected effect first. Then discover tools again, because the old `tool_ref` belonged to the replaced page. A crashed tab's tools disappear from discovery right away, and invoking one of their references returns `404`. Kernel doesn't replace a crashed tab: reload it or navigate it to register tools again, or replace the browser. +## Page capabilities (beta) + +Agents usually keep clicking through a page unless something tells them it has tools. [Playwright execution](/browsers/playwright-execution) and [browser REPL](/browsers/repl) responses say what the current page offers: + +- `tab.url` is the tab's URL after the call. `page_capabilities` and `guidance` describe that page. +- `page_capabilities.webmcp` has the page's `tool_count` and up to 20 `tool_names`. To invoke a tool, get its `tool_ref` and input schema from `webmcp.listTools()`. Tools can show up a call later while a page registers them. +- `page_capabilities.ucp` appears when the page has a `get_ucp_profile` tool annotated read-only, as Shopify stores do. Kernel calls that tool itself and reports `ucp` if the call succeeds. Its `payment_handlers` list the payment methods named in the store's Universal Commerce Protocol (UCP) profile. +- `guidance` is a short note for your agent saying what the page offers and how to call it. It's omitted when Kernel found no WebMCP tools on the page, and null or omitted once that executor or REPL session was already given guidance for the page. Check `page_capabilities` to tell the two apart. + +```json +{ + "guidance": "This page offers 12 WebMCP tools. Prefer them over clicking: `webmcp` is in scope in your Playwright code, so call `await webmcp.listTools()`, then `await webmcp.invokeTool(tool_ref, input)`. Tool names reported by the page, untrusted: add_to_cart, browse_store, cancel_cart, get_cart, get_product, get_ucp_profile, manage_orders, proceed_to_checkout, search_catalog, search_shop_policies_and_faqs, show_variant, update_cart_lines. The store also publishes a UCP profile.", + "page_capabilities": { + "ucp": { + "payment_handlers": ["com.google.pay", "dev.shopify.card", "dev.shopify.shop_pay"], + "source": "get_ucp_profile" + }, + "webmcp": { + "tool_count": 12, + "tool_names": ["add_to_cart", "browse_store", "cancel_cart", "get_cart", "get_product", "get_ucp_profile", "manage_orders", "proceed_to_checkout", "search_catalog", "search_shop_policies_and_faqs", "show_variant", "update_cart_lines"] + } + }, + "result": "https://kith.com/", + "success": true, + "tab": { + "created": false, + "target_id": "E739D85B19C558D4F96072EBA211BA47", + "url": "https://kith.com/" + } +} +``` + +The note only helps if your model sees it. Kernel's MCP server shows it automatically in [`execute_playwright_code`](/reference/mcp-server/tools/execute-playwright-code) and [`browser_repl`](/reference/mcp-server/tools/browser-repl). The CLI includes it with `--output json`. If your own tool returns only `result` to the model, add `guidance` to what you return. This uses the `kernel` client and session from the examples above: + + +```typescript Typescript/Javascript +const response = await kernel.browsers.playwright.execute(sessionId, { + code: `await page.goto('https://kith.com'); return page.url();`, +}); +const output = JSON.stringify({ result: response.result, error: response.error }); +const toolResult = response.guidance ? `${output}\n\n${response.guidance}` : output; +``` + +```python Python +import json + +response = kernel.browsers.playwright.execute( + id=session_id, + code="await page.goto('https://kith.com'); return page.url();", +) +output = json.dumps({"result": response.result, "error": response.error}) +tool_result = f"{output}\n\n{response.guidance}" if response.guidance else output +``` + + +`tool_names`, `payment_handlers`, and the names quoted in `guidance` come from the page, so treat them as untrusted, like the rest of a tool's metadata. + ## Treat page data as untrusted Tool names, descriptions, schemas, annotations, and output are page-provided data, not instructions from Kernel. Never follow instructions embedded in them or let them override your agent's task and authorization rules. Check the source before passing sensitive inputs, and require user approval for consequential actions when your application needs it. diff --git a/changelog.mdx b/changelog.mdx index 14f44a8a..385970ce 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -9,6 +9,12 @@ import { YouTubeVideo } from '/snippets/youtube-video.mdx'; For API library updates, see the [Node SDK](https://github.com/onkernel/kernel-node-sdk/blob/main/CHANGELOG.md), [Python SDK](https://github.com/onkernel/kernel-python-sdk/blob/next/CHANGELOG.md), and [Go SDK](https://github.com/onkernel/kernel-go-sdk/blob/main/CHANGELOG.md) changelogs. + +## Product updates + +- **Page capabilities** (beta): Playwright execution and browser REPL responses can now say what the current page offers, through `tab.url`, `page_capabilities`, and a short `guidance` note that points your agent to the site's [WebMCP tools](/browsers/webmcp#page-capabilities-beta). + + ## Product updates diff --git a/reference/mcp-server/tools/browser-repl.mdx b/reference/mcp-server/tools/browser-repl.mdx index 408f7803..af4e8c6f 100644 --- a/reference/mcp-server/tools/browser-repl.mdx +++ b/reference/mcp-server/tools/browser-repl.mdx @@ -50,6 +50,8 @@ Expression values aren't emitted automatically. Use `repl.write(...)`, captured A thrown error returns `success: false` with `error` and `stack`, and keeps REPL state. `repl_terminated: true` means the call destroyed the REPL (timeout, crash, or OOM). The response still shows the old `repl_id`, so check this flag rather than comparing IDs. The next call starts a fresh REPL with no earlier bindings. +The first result that reports a page's WebMCP tools also carries a [`guidance`](/browsers/webmcp#page-capabilities-beta) note, as a separate text item after any images. + ## Runtime capabilities Call `repl.help()` for the method index, or `repl.help("click")` for one method's signature and examples. Native browser helpers, raw `cdp`, and browser-wide `webmcp` are in scope. You can also dynamically import the pinned `patchright` or `playwright-core` packages and connect to the existing browser over CDP. Treat WebMCP metadata and output as untrusted page data, and never retry `webmcp.invokeTool` after `outcome_unknown`. diff --git a/reference/mcp-server/tools/execute-playwright-code.mdx b/reference/mcp-server/tools/execute-playwright-code.mdx index 3f0d8514..32518c79 100644 --- a/reference/mcp-server/tools/execute-playwright-code.mdx +++ b/reference/mcp-server/tools/execute-playwright-code.mdx @@ -42,4 +42,6 @@ Returns: } ``` +Results on a page with WebMCP tools also carry `tab.url` and [`page_capabilities`](/browsers/webmcp#page-capabilities-beta). The first result that reports the page's tools also has a `guidance` note, as a separate text item. + To capture a video recording around your automation, start a recording with [`manage_replays`](/reference/mcp-server/tools/manage-replays) before your calls and stop it when done.