Files

WebMCP tools and demos with Moli

These demos open public WebMCP sites in Moli, discover their native tools over CDP, invoke them, and check both the tool responses and the page state. No model account or API key is required: the scripts supply the tool arguments directly.

Operate any WebMCP site

webmcp.py accepts a site URL and uses the site's native tool catalog. Build Moli with cargo build --release -p moli, then list a site's tools and full schemas:

uv run moli-playground/webmcp/webmcp.py \
  https://googlechromelabs.github.io/webmcp-tools/demos/pizza-maker/ list

Call a tool with JSON arguments:

uv run moli-playground/webmcp/webmcp.py \
  https://googlechromelabs.github.io/webmcp-tools/demos/pizza-maker/ \
  call set_pizza_size --input '{"size":"Large"}'

--input @arguments.json reads a file; --input - reads JSON from stdin. Input must be a JSON object. Tool responses go to stdout as JSON, including the native status, output, and any execution error. A failed one-shot call exits with status

  1. A site with no registered tools produces an empty list.

Each one-shot command opens a new page. To make several calls on the same page, use the interactive shell:

uv run moli-playground/webmcp/webmcp.py \
  https://googlechromelabs.github.io/webmcp-tools/demos/pizza-maker/ shell

Inside the shell:

tools
schema set_pizza_size
call set_pizza_size {"size":"Large"}
wait <invocationId>
call add_topping {"topping":"🍍","size":"Large","count":3}
wait <invocationId>
quit

Use the invocation ID printed by each call. result ID shows its current status, wait ID waits for completion, and cancel ID cancels a pending call. The shell keeps receiving tool additions, removals, and responses while waiting for your next command. Commands may also be piped into the shell. Pending calls started by this session are cancelled when it exits.

For declarative forms that need confirmation, run call NAME JSON, inspect the prepared form in your attached page, then use confirm ID and wait ID. Confirmation targets the form identified by the native tool's node, including forms in child frames. For a one-shot call, --confirm explicitly submits the form after filling. Without it, a manual form call reports that confirmation is required before starting an invocation.

The catalog includes tools in child frames. If a name occurs in several frames, select --frame-id ID or use frame ID in the shell. frame main selects the main frame; frame all returns to the complete catalog. Frame IDs belong to the current page, so use the shell or attach to that page when selecting a child.

To reuse an authenticated or already prepared page in an existing release Moli server:

uv run moli-playground/webmcp/webmcp.py - shell \
  --cdp-endpoint http://127.0.0.1:9222 --target-id TID-1

The URL - preserves the current page without navigating. --target-id requires --cdp-endpoint; the script leaves that page and server open on exit. The target IDs can be obtained from the server's /json/list endpoint.

The CLI waits two seconds after page load to collect initial registrations; increase --wait-for-tools for sites that register tools later. It also supports the release binary, proxy, and timeout options listed below. Sites must expose native WebMCP tools; a remote MCP endpoint or static inventory alone is not a browser tool registration.

Run the preset demos

From the repository root, build a release Moli binary with native WebMCP support and run all three demos:

cargo build --release -p moli
uv run moli-playground/webmcp/webmcp_cdp_demo.py

The script starts moli serve with a temporary profile and an available local port, then closes it after the run. It uses target/release/moli by default and rejects binary paths containing a debug directory. uv installs the script's Python dependency automatically.

Run a single scenario:

uv run moli-playground/webmcp/webmcp_cdp_demo.py --demo booking
uv run moli-playground/webmcp/webmcp_cdp_demo.py --demo bistro
uv run moli-playground/webmcp/webmcp_cdp_demo.py --demo pizza
Demo Tool sequence What it checks
booking getAvailability → bookSlot → cancelBooking Choose an available slot, read its confirmation ID from the structured result, verify the visible confirmation, then cancel and check that the widget resets.
bistro book_table_le_petit_bistro → regular submit button Native declarative form filling, :tool-form-active, submitter focus, pending result before confirmation, and the response supplied through SubmitEvent.respondWith().
pizza manage_pizza → set_pizza_size → set_pizza_style → add_topping × 2 Sequential imperative calls produce a large BBQ pizza with three pineapple and five bacon toppings in the page.

The bistro uses the site's default form, which waits for confirmation. The demo first checks the prepared form, then clicks its normal submit button to simulate the visitor confirming. Dates are computed at runtime; the booking scenario uses the availability returned by the site.

Progress goes to stderr. The JSON report on stdout includes the discovered tool schemas, invocation IDs, WebMCP.toolResponded events, and the final page state. Any failed scenario makes the process exit with status 1.

uv run moli-playground/webmcp/webmcp_cdp_demo.py \
  --output /tmp/moli-webmcp-results.json

Explore other sites

List tools without invoking them:

uv run moli-playground/webmcp/webmcp_cdp_demo.py --demo pizza --list-tools

uv run moli-playground/webmcp/webmcp_cdp_demo.py --list-tools \
  --url https://microsoftedge.github.io/webmcp-labs/pizza-order/

The URL inspector reports tools registered in the page's main frame. It waits for at least one native tool and fails if the site exposes none within the timeout. It does not infer tools from a static manifest.

Useful options:

  • --moli-bin /path/to/release/moli selects a release binary explicitly.
  • --cdp-endpoint http://127.0.0.1:9222 reuses an existing release Moli server; the script opens and closes its own tabs and leaves the server running.
  • --http-proxy http://127.0.0.1:7890 configures a server started by the script.
  • --timeout 90 increases command, event, and HTTP timeouts in seconds.
  • --startup-timeout 30 gives a newly started server more time to become ready.

External WebMCP usage

Research and Moli verification performed on 2026-10-05. The runtime checks below used target/release/moli, built with cargo build --release -p moli. The Google Chrome Labs directory was a starting point; the links below point to the integrations and their own documentation or source.

Integration Published use Verification in this playground
Google Chrome Labs booking · source Availability queries, reservations, and cancellation. booking passed all three native calls and widget checks.
Le Petit Bistro · source Restaurant reservation using HTML form tool attributes. bistro passed native filling, confirmation, and response checks.
Google Chrome Labs pizza maker · source Tools update pizza size, style, layers, and toppings. pizza discovered seven tools and passed five native calls and page checks.
Microsoft Edge Contoso Pizza · source Menu browsing and cart management; the available tools change with order state. Native discovery verified: the initial page exposes browse and create-order. Other order states were not exercised.
BestPrice · tool inventory · source A shopping comparison site with page tools for product search, listing filters, offers, and price history. Its published WebMCP documentation and inventory were reviewed; not tested in Moli here.
Open for Agents · demo WordPress and WooCommerce content/product tools, plus form preparation for visitors to confirm. Its integration documentation was reviewed; not tested in Moli here.

The three runnable scenarios are public sample apps. BestPrice and Open for Agents show how the same API is being integrated into shopping and CMS workflows. Some providers also publish remote MCP endpoints; those are separate from the browser's WebMCP tool registry.

Native execution path

The runner enables the WebMCP CDP domain, consumes WebMCP.toolsAdded and WebMCP.toolsRemoved, calls WebMCP.invokeTool, and waits for WebMCP.toolResponded. It also checks that document.modelContext is an instance of the browser's native ModelContext.

The bistro and pizza sites ship their own compatibility polyfill, which returns early when native document.modelContext exists. The runner supplies no polyfill and invokes tools through Moli's registry. Runtime.evaluate reads the page state and performs the bistro's ordinary confirmation click.

The CLI and demos share webmcp_client.py, including release server startup, CDP event handling, and invocation tracking. Run the offline CLI integration checks with a release binary already built:

uv run --with websockets python3 -m unittest discover \
  -s moli-playground/webmcp -p test_webmcp.py -v

The checks cover shared page state, duplicate names across frames, dynamic tool registration/removal, cancellation, exact form confirmation with two pending forms, execution errors, and preserving an attached page.

These demos need access to the external pages and their dependencies, including GitHub Pages and the bistro's DOMPurify module on esm.sh. A network error or a changed tool/schema/page structure is reported as a failure. They are manual playground examples rather than offline CI fixtures.