Overview
WebMCP lets a page register tools on document.modelContext for whatever agent is driving the browser. With the webmcp feature, dioxus-docs-kit registers your docs as four read-only tools, so an agent searches the index and reads Markdown source instead of scraping the rendered page.
This site has them on. Open it in a WebMCP-capable browser or agent and call docs_list_pages.
The tools are read-only. None of them navigates or changes what the visitor sees.
Setup
Enable the feature
dioxus-docs-kit = { version = "0.7", features = ["webmcp"] }It is off by default because it pulls webmcp-rs and schemars into the wasm.
Mount the component
Put DocsWebMcp {} anywhere below use_docs_providers. It renders nothing. The registrations live exactly as long as the mount, so leaving the docs section unregisters them.
rsx! {
DocsLayout {
header: rsx! { /* ... */ },
DocsWebMcp {}
Outlet::<Route> {}
}
}Load the polyfill
Chrome 153+ has document.modelContext natively; 149 to 152 need the origin trial or chrome://flags/#enable-webmcp-testing. Every other browser needs Google's WebMCP polyfill (Apache-2.0), and it has to run before the wasm starts, because the tools register on first render. That rules out a component: it goes in index.html.
The polyfill is not part of the crate. Copy it from this repo's assets/webmcp-polyfill.js, then pin it as an unhashed asset so the URL is stable:
<head>
<script src="/assets/webmcp-polyfill.js"></script>
</head>The polyfill returns early when the browser has the native API.
Tools
Every tool replies with one JSON text block. Paths are content paths, the same ones you list in _nav.json, and every result carries the page URL so the agent can send the visitor there.
| Tool | Arguments | Returns |
|---|---|---|
docs_search |
query, optional limit (default 10, max 50) |
Ranked section-level hits with title, heading, breadcrumb, a snippet and the URL |
docs_get_page |
path |
The page's Markdown source plus title, description and tab |
docs_list_pages |
none | Every page grouped like the sidebar, API endpoints included |
docs_get_api_operation |
path |
One OpenAPI operation: method, endpoint, parameters, request body, responses and a ready curl command |
docs_get_page and docs_get_api_operation accept whatever shape an agent hands back: a full URL, a leading slash, the docs base path, a .md suffix or a #anchor are all stripped. A miss returns a soft error that names the nearest real pages.
The docs_ prefix keeps the tools clear of whatever else your page registers. WebMCP rejects a second tool with an existing name, and use_tool only logs that rejection, so an unprefixed collision would silently drop one side.
Calling them by hand
Open the console on this site:
const ctx = document.modelContext;
const search = (await ctx.getTools()).find(t => t.name === "docs_search");
// Chrome 153 and 154 only parse JSON-string arguments and return the result
// JSON-stringified; the polyfill and Chrome 155+ take and return objects.
let reply = await ctx.executeTool(search, JSON.stringify({ query: "theme toggle" }));
if (typeof reply === "string") reply = JSON.parse(reply);
JSON.parse(reply.content[0].text).results;scripts/browser-smoke.py in the repo runs the same calls against every tool in CI.