← WebMCPCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to WebMCP
Snapshot Sep 30, 2026 · 23:01 UTC · version 0.1.1
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Implement task-completing imperative WebMCP tools using document.modelContext.registerTool.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 298
}
],
"name": "webmcp-site-author",
"skill_md_contents": "---\nname: webmcp-site-author\ndescription: Implement task-completing imperative WebMCP tools using document.modelContext.registerTool.\n---\n\n# WebMCP\n\nWebMCP is a proposed browser standard that lets websites expose their functionality directly to AI agents as structured tools.\n\nIt exposes declarative and imperative APIs, and the full specification can be found here https://webmachinelearning.github.io/webmcp/\n\nThe ChatGPT implementation only supports the imperative inerface\n\n## API structure\n\n```ts\ninterface Document {\n readonly modelContext?: ModelContext; // Page-scoped registry; feature-detect support.\n}\n\ninterface ModelContext {\n registerTool(\n tool: {\n name: string; // Unique, stable action identifier.\n description: string; // What the tool does and when to use it.\n inputSchema: object; // JSON Schema describing accepted input.\n execute(input: unknown): unknown | Promise<unknown>; // Validate, act, return result.\n title?: string; // Human-readable display label.\n annotations?: {\n // Behavioral hints, not security boundaries.\n readOnlyHint?: boolean; // True only when no state changes.\n untrustedContentHint?: boolean; // True for external or user-generated output.\n };\n },\n options?: {\n signal?: AbortSignal; // Abort to unregister this tool.\n },\n ): void | Promise<void>; // Register one tool for this page.\n}\n```\n\n## Example call site\n\n```ts\nconst context =\n typeof document === \"undefined\" ? undefined : document.modelContext;\nif (!context?.registerTool) return;\nconst lifecycle = new AbortController();\n\ntry {\n void Promise.resolve(\n context.registerTool(\n {\n name: \"create_booking\",\n title: \"Create booking\",\n description:\n \"Book the selected slot and update the visible reservation.\",\n inputSchema: {\n type: \"object\",\n properties: { slotId: { type: \"string\" } },\n required: [\"slotId\"],\n additionalProperties: false,\n },\n annotations: { readOnlyHint: false, untrustedContentHint: false },\n async execute(input) {\n const booking = await bookSlot(validateInput(input));\n return { id: booking.id, status: \"confirmed\" };\n },\n },\n { signal: lifecycle.signal },\n ),\n ).catch(reportError);\n} catch (error) {\n reportError(error);\n}\n\nreturn () => lifecycle.abort();\n```\n\n## Tool-design rules\n\n- Distinguish **read**, **navigate/start**, **stage/configure**, and **complete** in names and descriptions. `create_event` means an event is created; `start_event_creation` only opens or prepares a flow. Never conceal side effects in an ambiguous verb.\n- Prefer batched APIs where possible, rather than requiring clients to write loops.\n- Return concise JSON-serializable results only after the action and visible state finish updating.\n- Register once client-side, clean up with `AbortSignal`, and handle unsupported browsers and registration failures.\n"
}SHA-256 of public snapshot: c5789b969254daa6cb63f7f6fb83c8854e372ee7ff15c195ebfb8f063e8ba2dc