OpenAPI describes your HTTP surface. WebMCP exposes selected operations to an agent inside the signed-in browser. Both should be projections of the same operation catalogue used by MCP.
Register a browser tool
const modelContext = document.modelContext
modelContext?.registerTool({
name: "list_products",
description: "List products with current price and availability.",
inputSchema: {
type: "object",
properties: { query: { type: "string" } },
additionalProperties: false
},
annotations: { readOnlyHint: true },
execute: async ({ query }) => {
const response = await fetch(`/api/products?q=${encodeURIComponent(query ?? "")}`)
if (!response.ok) throw new Error(`products request failed: ${response.status}`)
return response.json()
}
})
Feature-detect document.modelContext. WebMCP remains an evolving Community
Group draft, so keep the normal HTTP UI functional when the browser does not
provide it.
Reuse the browser session safely
The fetch call stays in the signed-in origin, so the browser applies the app’s HttpOnly session without revealing it to the tool result or agent. Mutating tools also need the app’s normal CSRF and idempotency contract.
Never put a session bearer in localStorage, a tool description, tool arguments, the page URL, or MCP output.
Generate OpenAPI
Publish OpenAPI 3.1 at /openapi.json. Include stable operation IDs, request
and response schemas, authentication requirements, idempotency headers, rate
limit responses, and problem details. The agent-ready package generates the
catalogue from Surface.operations.
Content for agents
Provide Markdown twins through a .md path, ?format=md, or
Accept: text/markdown. Keep headings, code, tables, and links; remove header,
sidebar, cookie banner, and other visual chrome. Link the Markdown alternate in
the HTML head.
This documentation site exposes search_ferrite_docs and read_ferrite_doc
as WebMCP tools and serves Markdown from the same MDX collection.